OSDN Git Service

・未保存確認の改善:自動生成したMIDIシーケンスが未保存の場合にも確認ダイアログを出すようにした
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 20 Mar 2017 16:53:56 +0000 (01:53 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 20 Mar 2017 16:53:56 +0000 (01:53 +0900)
・リファクタリング:ラムダ式への置き換えなど(Java8からの文法)

24 files changed:
src/camidion/chordhelper/AboutMessagePane.java [new file with mode: 0644]
src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/ChordTextField.java
src/camidion/chordhelper/MidiChordHelper.java
src/camidion/chordhelper/anogakki/AnoGakkiPane.java
src/camidion/chordhelper/chorddiagram/CapoSelecterView.java
src/camidion/chordhelper/chorddiagram/ChordDiagram.java
src/camidion/chordhelper/chorddiagram/ChordDiagramDisplay.java
src/camidion/chordhelper/mididevice/MidiCablePane.java
src/camidion/chordhelper/mididevice/MidiDeviceDesktopPane.java
src/camidion/chordhelper/mididevice/MidiDeviceDialog.java
src/camidion/chordhelper/mididevice/MidiDeviceInOutType.java
src/camidion/chordhelper/mididevice/MidiDeviceTreeModel.java
src/camidion/chordhelper/mididevice/MidiSequencerModel.java
src/camidion/chordhelper/mididevice/SequencerMeasureView.java
src/camidion/chordhelper/midieditor/Base64Dialog.java
src/camidion/chordhelper/midieditor/KeySignatureLabel.java
src/camidion/chordhelper/midieditor/MidiEventDialog.java
src/camidion/chordhelper/midieditor/MidiMessageForm.java
src/camidion/chordhelper/midieditor/MidiSequenceEditorDialog.java
src/camidion/chordhelper/midieditor/NewSequenceDialog.java
src/camidion/chordhelper/midieditor/PlaylistTableModel.java
src/camidion/chordhelper/midieditor/SequencerSpeedSlider.java
src/camidion/chordhelper/music/ChordProgression.java

diff --git a/src/camidion/chordhelper/AboutMessagePane.java b/src/camidion/chordhelper/AboutMessagePane.java
new file mode 100644 (file)
index 0000000..0598fff
--- /dev/null
@@ -0,0 +1,80 @@
+package camidion.chordhelper;
+
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JEditorPane;
+import javax.swing.JOptionPane;
+import javax.swing.event.HyperlinkEvent;
+
+import camidion.chordhelper.ChordHelperApplet.VersionInfo;
+/**
+ * バージョン情報表示欄
+ */
+public class AboutMessagePane extends JEditorPane {
+       private Action openAction;
+       /**
+        * このバージョン情報表示欄を開くためのアクションを返します。
+        */
+       public Action getOpenAction() { return openAction; }
+       /**
+        * バージョン情報表示欄を構築します。
+        * @param imageIcon 画像アイコン
+        */
+       public AboutMessagePane(ImageIcon imageIcon) {
+               super("text/html", "");
+               openAction = new AbstractAction() {
+                       {
+                               putValue(NAME, "Version info");
+                               putValue(SHORT_DESCRIPTION, VersionInfo.NAME + " " + VersionInfo.VERSION);
+                       }
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               JOptionPane.showMessageDialog(
+                                       null, AboutMessagePane.this, getValue(NAME).toString(),
+                                       JOptionPane.INFORMATION_MESSAGE, imageIcon
+                               );
+                       }
+               };
+               boolean linkEnabled = Desktop.isDesktopSupported();
+               String linkString = VersionInfo.URL;
+               String tooltip = null;
+               if( linkEnabled ) {
+                       tooltip = "Click to open on web browser - Webブラウザで開く";
+                       linkString = "<a href=\""+linkString+"\" title=\""+tooltip+"\">"+linkString+"</a>";
+               }
+               setText("<html><center><font size=\"+1\">" +
+                               VersionInfo.NAME + "</font> " +
+                               VersionInfo.VERSION + "<br/><br/>" +
+                               VersionInfo.COPYRIGHT + " " +
+                               VersionInfo.AUTHER + "<br/>" +
+                               linkString + "</center></html>");
+               setToolTipText(tooltip);
+               setOpaque(false);
+               putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+               setEditable(false);
+               if( ! linkEnabled ) return;
+               URI uri;
+               try {
+                       uri = new URI(VersionInfo.URL);
+               }catch( URISyntaxException use ) {
+                       use.printStackTrace();
+                       return;
+               }
+               addHyperlinkListener(e->{
+                       if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) {
+                               try{
+                                       Desktop.getDesktop().browse(uri);
+                               }catch(IOException ioe) {
+                                       ioe.printStackTrace();
+                               }
+                       }
+               });
+       }
+}
\ No newline at end of file
index 8dca4d0..2efb985 100644 (file)
@@ -1,53 +1,39 @@
 package camidion.chordhelper;
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.awt.Desktop;
 import java.awt.Dimension;
 import java.awt.Image;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.awt.event.InputEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.IOException;
-import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.AccessControlException;
 import java.util.Arrays;
 
 import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MetaEventListener;
 import javax.sound.midi.MetaMessage;
 import javax.sound.midi.Sequence;
 import javax.sound.midi.Sequencer;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.ImageIcon;
 import javax.swing.JApplet;
 import javax.swing.JButton;
 import javax.swing.JComponent;
-import javax.swing.JEditorPane;
 import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JSlider;
 import javax.swing.JSplitPane;
 import javax.swing.JToggleButton;
 import javax.swing.SwingUtilities;
 import javax.swing.border.Border;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
 
 import camidion.chordhelper.anogakki.AnoGakkiPane;
 import camidion.chordhelper.chorddiagram.CapoComboBoxModel;
@@ -94,7 +80,9 @@ public class ChordHelperApplet extends JApplet {
         * 未保存の修正済み MIDI ファイルがあるかどうか調べます。
         * @return 未保存の修正済み MIDI ファイルがあれば true
         */
-       public boolean isModified() { return playlistModel.isModified(); }
+       public boolean isModified() {
+               return playlistModel.getSequenceModelList().stream().anyMatch(m -> m.isModified());
+       }
        /**
         * 指定された小節数の曲を、乱数で自動作曲してプレイリストへ追加します。
         * @param measureLength 小節数
@@ -119,10 +107,9 @@ public class ChordHelperApplet extends JApplet {
                try {
                        return playlistModel.addSequenceFromURL(midiFileUrl);
                } catch( URISyntaxException|IOException|InvalidMidiDataException e ) {
-                       midiEditor.showWarning(e.getMessage());
+                       midiEditor.showWarning(e);
                } catch( AccessControlException e ) {
-                       e.printStackTrace();
-                       midiEditor.showError(e.getMessage());
+                       midiEditor.showError(e);
                }
                return -1;
        }
@@ -149,8 +136,7 @@ public class ChordHelperApplet extends JApplet {
                try {
                        return playlistModel.addSequence(d.getMIDIData(), filename);
                } catch (Exception e) {
-                       e.printStackTrace();
-                       midiEditor.showWarning(e.toString());
+                       midiEditor.showWarning(e);
                        return -1;
                }
        }
@@ -159,7 +145,9 @@ public class ChordHelperApplet extends JApplet {
         * シーケンサへロードして再生します。
         * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public void play() throws InvalidMidiDataException { play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex()); }
+       public void play() throws InvalidMidiDataException {
+               play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex());
+       }
        /**
         * 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスを、
         * シーケンサへロードして再生します。
@@ -283,7 +271,7 @@ public class ChordHelperApplet extends JApplet {
         */
        public static class VersionInfo {
                public static final String NAME = "MIDI Chord Helper";
-               public static final String VERSION = "Ver.20170304.1";
+               public static final String VERSION = "Ver.20170320.1";
                public static final String COPYRIGHT = "Copyright (C) 2004-2017";
                public static final String AUTHER = "@きよし - Akiyoshi Kamide";
                public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
@@ -296,91 +284,12 @@ public class ChordHelperApplet extends JApplet {
                                + " " + VersionInfo.AUTHER
                                + " " + VersionInfo.URL;
        }
-       private class AboutMessagePane extends JEditorPane {
-               URI uri;
-               public AboutMessagePane() {
-                       super("text/html", "");
-                       boolean linkEnabled = Desktop.isDesktopSupported();
-                       String linkString = VersionInfo.URL;
-                       String tooltip = null;
-                       if( linkEnabled ) {
-                               tooltip = "Click this URL to open with your web browser - URLをクリックしてWebブラウザで開く";
-                               linkString = "<a href=\""+linkString+"\" title=\""+tooltip+"\">"+linkString+"</a>";
-                       }
-                       setText("<html><center><font size=\"+1\">" +
-                                       VersionInfo.NAME + "</font> " +
-                                       VersionInfo.VERSION + "<br/><br/>" +
-                                       VersionInfo.COPYRIGHT + " " +
-                                       VersionInfo.AUTHER + "<br/>" +
-                                       linkString + "</center></html>");
-                       setToolTipText(tooltip);
-                       setOpaque(false);
-                       putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
-                       setEditable(false);
-                       //
-                       // メッセージ内の <a href=""> ~ </a> によるリンクを
-                       // 実際に機能させる(ブラウザで表示されるようにする)ための設定
-                       //
-                       if( ! linkEnabled ) return;
-                       try {
-                               uri = new URI(VersionInfo.URL);
-                       }catch( URISyntaxException use ) {
-                               use.printStackTrace();
-                               return;
-                       }
-                       addHyperlinkListener(new HyperlinkListener() {
-                               public void hyperlinkUpdate(HyperlinkEvent e) {
-                                       if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) {
-                                               try{
-                                                       Desktop.getDesktop().browse(uri);
-                                               }catch(IOException ioe) {
-                                                       ioe.printStackTrace();
-                                               }
-                                       }
-                               }
-                       });
-               }
-               /**
-                * バージョン情報を開くアクション
-                */
-               public Action openAction = new AbstractAction() {
-                       {
-                               putValue(NAME, "Version info");
-                               putValue(SHORT_DESCRIPTION, VersionInfo.NAME + " " + VersionInfo.VERSION);
-                       }
-                       @Override
-                       public void actionPerformed(ActionEvent e) {
-                               JOptionPane.showMessageDialog(
-                                       null, AboutMessagePane.this, getValue(NAME).toString(),
-                                       JOptionPane.INFORMATION_MESSAGE, imageIcon
-                               );
-                       }
-               };
-       }
-       /**
-        * アプリケーションのイメージアイコン
-        */
-       public ImageIcon imageIcon;
-       /**
-        * アプリケーションのアイコンイメージ
-        */
-       public Image iconImage;
-       private static final String IMAGE_ICON_PATH = "midichordhelper.png";
-       private void loadIconImage() {
-               URL imageIconUrl = getClass().getResource(IMAGE_ICON_PATH);
-               if( imageIconUrl == null ) {
-                       System.out.println("Icon image " + IMAGE_ICON_PATH + " not found");
-               }
-               else {
-                       iconImage = (imageIcon = new ImageIcon(imageIconUrl)).getImage();
-               }
-       }
        /**
         * ボタンの余白を詰めたいときに setMargin() の引数に指定するインセット
         */
        public static final Insets ZERO_INSETS = new Insets(0,0,0,0);
-       //
-       //
+
+       // GUIコンポーネント
        MidiSequenceEditorDialog midiEditor;
        PlaylistTableModel playlistModel;
        MidiSequencerModel sequencerModel;
@@ -403,8 +312,19 @@ public class ChordHelperApplet extends JApplet {
        private JToggleButton anoGakkiToggleButton;
        private MidiDeviceTreeModel deviceTreeModel;
 
+       // アイコン画像
+       private Image iconImage;
+       public Image getIconImage() { return iconImage; }
+       private ImageIcon imageIcon;
+       public ImageIcon getImageIcon() { return imageIcon; }
+
        public void init() {
-               loadIconImage();
+               // アイコン画像のロード
+               URL imageIconUrl = getClass().getResource("midichordhelper.png");
+               if( imageIconUrl != null ) {
+                       iconImage = (imageIcon = new ImageIcon(imageIconUrl)).getImage();
+               }
+               AboutMessagePane about = new AboutMessagePane(imageIcon);
                //
                // 背景色の取得
                rootPaneDefaultBgcolor = getContentPane().getBackground();
@@ -421,23 +341,20 @@ public class ChordHelperApplet extends JApplet {
                                }
                                public void chordChanged() { chordOn(); }
                        });
-                       capoSelecter.checkbox.addItemListener(new ItemListener() {
-                               public void itemStateChanged(ItemEvent e) {
-                                       chordOn();
-                                       keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
-                                       chordDiagram.clear();
-                               }
+                       capoSelecter.checkbox.addItemListener(e->{
+                               chordOn();
+                               keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+                               chordDiagram.clear();
                        });
-                       capoSelecter.valueSelecter.addActionListener(new ActionListener() {
-                               public void actionPerformed(ActionEvent e) {
-                                       chordOn();
-                                       keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
-                                       chordDiagram.clear();
-                               }
+                       capoSelecter.valueSelecter.addActionListener(e->{
+                               chordOn();
+                               keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+                               chordDiagram.clear();
                        });
                }};
                keysigLabel = new KeySignatureLabel() {{
                        addMouseListener(new MouseAdapter() {
+                               @Override
                                public void mousePressed(MouseEvent e) { chordMatrix.setKeySignature(getKey()); }
                        });
                }};
@@ -446,12 +363,13 @@ public class ChordHelperApplet extends JApplet {
                                @Override
                                public void pianoKeyPressed(int n, InputEvent e) { chordDiagram.clear(); }
                        });
-                       keySelecter.getKeysigCombobox().addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) {
-                                       chordMatrix.setKeySignature(keySelecter.getSelectedKey().transposedKey(-chordMatrix.capoSelecter.getCapo()));
-                               }
-                       });
+                       keySelecter.getKeysigCombobox().addActionListener(
+                               e -> chordMatrix.setKeySignature(
+                                       keySelecter.getSelectedKey().transposedKey(
+                                               -chordMatrix.capoSelecter.getCapo()
+                                       )
+                               )
+                       );
                        keyboardCenterPanel.keyboard.setPreferredSize(new Dimension(571, 80));
                }};
                VirtualMidiDevice guiMidiDevice = keyboardPanel.keyboardCenterPanel.keyboard.midiDevice;
@@ -476,11 +394,8 @@ public class ChordHelperApplet extends JApplet {
                keyboardPanel.setEventDialog(midiEditor.eventDialog);
                //
                // 歌詞表示
-               (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener(new ActionListener() {
-                       @Override
-                       public void actionPerformed(ActionEvent event) {
-                               chordMatrix.setSelectedChord(event.getActionCommand().trim().split("[ \t\r\n]")[0]);
-                       }
+               (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener((ActionEvent e)->{
+                       chordMatrix.setSelectedChord(e.getActionCommand().trim().split("[ \t\r\n]")[0]);
                });
                lyricDisplayDefaultBorder = lyricDisplay.getBorder();
                lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
@@ -488,91 +403,58 @@ public class ChordHelperApplet extends JApplet {
                // メタイベント(テンポ・拍子・調号)を受信して表示するリスナーを登録
                TempoSelecter tempoSelecter = new TempoSelecter() {{ setEditable(false); }};
                TimeSignatureSelecter timesigSelecter = new TimeSignatureSelecter() {{ setEditable(false); }};
-               sequencerModel.getSequencer().addMetaEventListener(new MetaEventListener() {
-                       @Override
-                       public void meta(MetaMessage msg) {
-                               switch(msg.getType()) {
-                               case 0x51: // Tempo (3 bytes) - テンポ
-                                       byte[] qpm = msg.getData();
-                                       if( SwingUtilities.isEventDispatchThread() ) {
-                                               tempoSelecter.setTempo(qpm);
-                                       } else {
-                                               // MIDIシーケンサのスレッドから呼ばれた場合、GUI更新は自分で行わず、
-                                               // AWTイベントディスパッチスレッドに依頼する。
-                                               SwingUtilities.invokeLater(new Runnable() {
-                                                       @Override
-                                                       public void run() { tempoSelecter.setTempo(qpm);}
-                                               });
-                                       }
-                                       break;
-                               case 0x58: // Time signature (4 bytes) - 拍子
-                                       byte[] timesig = msg.getData();
-                                       if( SwingUtilities.isEventDispatchThread() ) {
-                                               timesigSelecter.setValue(timesig);
-                                       } else {
-                                               SwingUtilities.invokeLater(new Runnable() {
-                                                       @Override
-                                                       public void run() { timesigSelecter.setValue(timesig);}
-                                               });
-                                       }
-                                       break;
-                               case 0x59: // Key signature (2 bytes) : 調号
-                                       Key key = new Key(msg.getData());
-                                       if( SwingUtilities.isEventDispatchThread() ) {
-                                               setKeySignature(key);
-                                       } else {
-                                               SwingUtilities.invokeLater(new Runnable() {
-                                                       @Override
-                                                       public void run() { setKeySignature(key); }
-                                               });
-                                       }
-                                       break;
-                               }
+               sequencerModel.getSequencer().addMetaEventListener(msg->{
+                       switch(msg.getType()) {
+                       case 0x51: // Tempo (3 bytes) - テンポ
+                               SwingUtilities.invokeLater(()->tempoSelecter.setTempo(msg.getData()));
+                               break;
+                       case 0x58: // Time signature (4 bytes) - 拍子
+                               SwingUtilities.invokeLater(()->timesigSelecter.setValue(msg.getData()));
+                               break;
+                       case 0x59: // Key signature (2 bytes) : 調号
+                               SwingUtilities.invokeLater(()->setKeySignature(new Key(msg.getData())));
+                               break;
                        }
-
                });
                //シーケンサーの時間スライダーの値が変わったときのリスナーを登録
                JLabel songTitleLabel = new JLabel();
-               sequencerModel.addChangeListener(new ChangeListener() {
-                       @Override
-                       public void stateChanged(ChangeEvent e) {
-                               SequenceTrackListTableModel sequenceTableModel = sequencerModel.getSequenceTrackListTableModel();
-                               int loadedSequenceIndex = playlistModel.indexOfSequenceOnSequencer();
-                               songTitleLabel.setText(
-                                       "<html>"+(
-                                               loadedSequenceIndex < 0 ? "[No MIDI file loaded]" :
-                                               "MIDI file " + loadedSequenceIndex + ": " + (
-                                                       sequenceTableModel == null ||
-                                                       sequenceTableModel.toString() == null ||
-                                                       sequenceTableModel.toString().isEmpty() ?
-                                                       "[Untitled]" :
-                                                       "<font color=maroon>"+sequenceTableModel+"</font>"
-                                               )
-                                       )+"</html>"
-                               );
-                               Sequencer sequencer = sequencerModel.getSequencer();
-                               chordMatrix.setPlaying(sequencer.isRunning());
-                               if( sequenceTableModel != null ) {
-                                       SequenceTickIndex tickIndex = sequenceTableModel.getSequenceTickIndex();
-                                       long tickPos = sequencer.getTickPosition();
-                                       tickIndex.tickToMeasure(tickPos);
-                                       chordMatrix.setBeat(tickIndex);
-                                       if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
-                                               MetaMessage msg;
-                                               msg = tickIndex.lastMetaMessageAt(
-                                                       SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPos
-                                               );
-                                               timesigSelecter.setValue(msg==null ? null : msg.getData());
-                                               msg = tickIndex.lastMetaMessageAt(
-                                                       SequenceTickIndex.MetaMessageType.TEMPO, tickPos
-                                               );
-                                               tempoSelecter.setTempo(msg==null ? null : msg.getData());
-                                               msg = tickIndex.lastMetaMessageAt(
-                                                       SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPos
-                                               );
-                                               if(msg == null) keysigLabel.clear();
-                                               else setKeySignature(new Key(msg.getData()));
-                                       }
+               sequencerModel.addChangeListener(e->{
+                       SequenceTrackListTableModel sequenceTableModel = sequencerModel.getSequenceTrackListTableModel();
+                       int loadedSequenceIndex = playlistModel.indexOfSequenceOnSequencer();
+                       songTitleLabel.setText(
+                               "<html>"+(
+                                       loadedSequenceIndex < 0 ? "[No MIDI file loaded]" :
+                                       "MIDI file " + loadedSequenceIndex + ": " + (
+                                               sequenceTableModel == null ||
+                                               sequenceTableModel.toString() == null ||
+                                               sequenceTableModel.toString().isEmpty() ?
+                                               "[Untitled]" :
+                                               "<font color=maroon>"+sequenceTableModel+"</font>"
+                                       )
+                               )+"</html>"
+                       );
+                       Sequencer sequencer = sequencerModel.getSequencer();
+                       chordMatrix.setPlaying(sequencer.isRunning());
+                       if( sequenceTableModel != null ) {
+                               SequenceTickIndex tickIndex = sequenceTableModel.getSequenceTickIndex();
+                               long tickPos = sequencer.getTickPosition();
+                               tickIndex.tickToMeasure(tickPos);
+                               chordMatrix.setBeat(tickIndex);
+                               if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
+                                       MetaMessage msg;
+                                       msg = tickIndex.lastMetaMessageAt(
+                                               SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPos
+                                       );
+                                       timesigSelecter.setValue(msg==null ? null : msg.getData());
+                                       msg = tickIndex.lastMetaMessageAt(
+                                               SequenceTickIndex.MetaMessageType.TEMPO, tickPos
+                                       );
+                                       tempoSelecter.setTempo(msg==null ? null : msg.getData());
+                                       msg = tickIndex.lastMetaMessageAt(
+                                               SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPos
+                                       );
+                                       if(msg == null) keysigLabel.clear();
+                                       else setKeySignature(new Key(msg.getData()));
                                }
                        }
                });
@@ -600,11 +482,7 @@ public class ChordHelperApplet extends JApplet {
                        add( Box.createHorizontalStrut(5) );
                        add( darkModeToggleButton = new JToggleButton(new ButtonIcon(ButtonIcon.DARK_MODE_ICON)) {{
                                setMargin(ZERO_INSETS);
-                               addItemListener(new ItemListener() {
-                                       public void itemStateChanged(ItemEvent e) {
-                                               innerSetDarkMode(darkModeToggleButton.isSelected());
-                                       }
-                               });
+                               addItemListener(e->innerSetDarkMode(darkModeToggleButton.isSelected()));
                                setToolTipText("Light / Dark - 明かりを点灯/消灯");
                                setBorder(null);
                        }});
@@ -614,12 +492,10 @@ public class ChordHelperApplet extends JApplet {
                                setMargin(ZERO_INSETS);
                                setBorder( null );
                                setToolTipText("あの楽器");
-                               addItemListener(new ItemListener() {
-                                       public void itemStateChanged(ItemEvent e) {
-                                               keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiPane
-                                               = anoGakkiToggleButton.isSelected() ? anoGakkiPane : null ;
-                                       }
-                               });
+                               addItemListener(
+                                       e -> keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiPane
+                                       = anoGakkiToggleButton.isSelected() ? anoGakkiPane : null
+                               );
                        }} );
                        add( Box.createHorizontalStrut(5) );
                        add( inversionOmissionButton = new InversionAndOmissionLabel() );
@@ -641,18 +517,18 @@ public class ChordHelperApplet extends JApplet {
                                setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
                                add(new JPanel() {{
                                        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( keysigLabel );
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( timesigSelecter );
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( tempoSelecter );
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( new SequencerMeasureView(sequencerModel) );
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( songTitleLabel );
-                                       add( Box.createHorizontalStrut(12) );
-                                       add( new JButton(midiEditor.openAction) {{ setMargin(ZERO_INSETS); }});
+                                       add(Box.createHorizontalStrut(12));
+                                       add(keysigLabel);
+                                       add(Box.createHorizontalStrut(12));
+                                       add(timesigSelecter);
+                                       add(Box.createHorizontalStrut(12));
+                                       add(tempoSelecter);
+                                       add(Box.createHorizontalStrut(12));
+                                       add(new SequencerMeasureView(sequencerModel));
+                                       add(Box.createHorizontalStrut(12));
+                                       add(songTitleLabel);
+                                       add(Box.createHorizontalStrut(12));
+                                       add(new JButton(midiEditor.openAction) {{ setMargin(ZERO_INSETS); }});
                                }});
                                add(new JPanel() {{
                                        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
@@ -660,17 +536,17 @@ public class ChordHelperApplet extends JApplet {
                                        add(new JSlider(sequencerModel));
                                        add(new SequencerTimeView(sequencerModel));
                                        add(Box.createHorizontalStrut(5));
-                                       add(new JButton(playlistModel.moveToTopAction) {{ setMargin(ZERO_INSETS); }});
-                                       add(new JButton(sequencerModel.moveBackwardAction) {{ setMargin(ZERO_INSETS); }});
-                                       add(new JToggleButton(sequencerModel.startStopAction));
-                                       add(new JButton(sequencerModel.moveForwardAction) {{ setMargin(ZERO_INSETS); }});
-                                       add(new JButton(playlistModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }});
-                                       add(new JToggleButton(playlistModel.toggleRepeatAction) {{ setMargin(ZERO_INSETS); }});
+                                       add(new JButton(playlistModel.getMoveToTopAction()) {{ setMargin(ZERO_INSETS); }});
+                                       add(new JButton(sequencerModel.getMoveBackwardAction()) {{ setMargin(ZERO_INSETS); }});
+                                       add(new JToggleButton(sequencerModel.getStartStopAction()));
+                                       add(new JButton(sequencerModel.getMoveForwardAction()) {{ setMargin(ZERO_INSETS); }});
+                                       add(new JButton(playlistModel.getMoveToBottomAction()) {{ setMargin(ZERO_INSETS); }});
+                                       add(new JToggleButton(playlistModel.getToggleRepeatAction()) {{ setMargin(ZERO_INSETS); }});
                                        add( Box.createHorizontalStrut(10) );
                                }});
                                add(new JPanel() {{
                                        add(new JButton(midiDeviceDialog.openAction));
-                                       add(new JButton((new AboutMessagePane()).openAction));
+                                       add(new JButton(about.getOpenAction()));
                                }});
                        }});
                }};
@@ -750,7 +626,7 @@ public class ChordHelperApplet extends JApplet {
        }
 
        private void setKeySignature(Key key) {
-               keysigLabel.setKeySignature(key);
+               keysigLabel.setKey(key);
                chordMatrix.setKeySignature(key);
        }
 
@@ -758,7 +634,7 @@ public class ChordHelperApplet extends JApplet {
        /**
         * 和音を発音します。
         * <p>この関数を直接呼ぶとアルペジオが効かないので、
-        * chord_matrix.setSelectedChord() を使うことを推奨
+        * chordMatrix.setSelectedChord() を使うことを推奨
         * </p>
         */
        public void chordOn() {
index 1d0c65d..1e1f88e 100644 (file)
@@ -4,8 +4,6 @@ import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.sound.midi.MetaEventListener;
-import javax.sound.midi.MetaMessage;
 import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
 
@@ -26,31 +24,18 @@ public class ChordTextField extends JTextField {
                // To reduce resized height, set maximum size to screen size.
                //
                setMaximumSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
-               (this.sequencerModel = sequencerModel).getSequencer().addMetaEventListener(new MetaEventListener() {
-                       @Override
-                       public void meta(MetaMessage msg) {
-                               int t = msg.getType();
-                               switch(t) {
-                               case 0x01: // Text(任意のテキスト:コメントなど)
-                               case 0x05: // Lyrics(歌詞)
-                               case 0x02: // Copyright(著作権表示)
-                               case 0x03: // Sequence Name / Track Name(曲名またはトラック名)
-                               case 0x06: // Marker
-                                       byte[] d = msg.getData();
-                                       if( SwingUtilities.isEventDispatchThread() ) {
-                                               addText(t,d);
-                                       } else {
-                                               // MIDIシーケンサのEDTから呼ばれた場合
-                                               // 表示処理をSwingのEDTに振り直す
-                                               SwingUtilities.invokeLater(new Runnable() {
-                                                       @Override
-                                                       public void run() { addText(t,d); }
-                                               });
-                                       }
-                                       break;
-                               default:
-                                       break;
-                               }
+               (this.sequencerModel = sequencerModel).getSequencer().addMetaEventListener(msg->{
+                       int t = msg.getType();
+                       switch(t) {
+                       case 0x01: // Text(任意のテキスト:コメントなど)
+                       case 0x05: // Lyrics(歌詞)
+                       case 0x02: // Copyright(著作権表示)
+                       case 0x03: // Sequence Name / Track Name(曲名またはトラック名)
+                       case 0x06: // Marker
+                               SwingUtilities.invokeLater(()->addText(t, msg.getData()));
+                               break;
+                       default:
+                               break;
                        }
                });
        }
@@ -99,10 +84,7 @@ public class ChordTextField extends JTextField {
                        String currentText = getText();
                        if(
                                currentText != null && ! currentText.isEmpty()
-                               && (
-                                       isSoon ||
-                                       ! additionalText.isEmpty() && additionalText.length() <= 8
-                               )
+                               && (isSoon || ! additionalText.isEmpty() && additionalText.length() <= 8)
                        ) {
                                // 既存歌詞がある場合、頻繁に来たか短い歌詞だったら追加
                                currentText += " " + additionalText;
index 93f8b9a..5fc3014 100644 (file)
@@ -23,10 +23,7 @@ import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.SwingUtilities;
 import javax.swing.WindowConstants;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
 
 import camidion.chordhelper.midieditor.PlaylistTableModel;
 import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
@@ -42,11 +39,8 @@ public class MidiChordHelper {
         * @throws Exception 何らかの異常が発生した場合にスローされる
         */
        public static void main(String[] args) throws Exception {
-               for( String arg : args ) fileList.add(new File(arg));
-               SwingUtilities.invokeLater(new Runnable(){
-                       @Override
-                       public void run() { new AppletFrame(new ChordHelperApplet(), fileList); }
-               });
+               for(String arg : args) fileList.add(new File(arg));
+               SwingUtilities.invokeLater(()->new AppletFrame(new ChordHelperApplet(), fileList));
        }
        private static class AppletFrame extends JFrame implements AppletStub, AppletContext {
                private JLabel status_ = new JLabel("Welcome to "+ChordHelperApplet.VersionInfo.NAME) {
@@ -64,13 +58,13 @@ public class MidiChordHelper {
                        }
                        setTitle(title);
                }
-               public AppletFrame(final ChordHelperApplet applet, List<File> fileList) {
+               public AppletFrame(ChordHelperApplet applet, List<File> fileList) {
                        setTitle(ChordHelperApplet.VersionInfo.NAME);
                        add( applet, BorderLayout.CENTER );
                        add( status_, BorderLayout.SOUTH );
                        applet.setStub(this);
                        applet.init();
-                       setIconImage(applet.iconImage);
+                       setIconImage(applet.getIconImage());
                        setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
                        pack();
                        setLocationRelativeTo(null);
@@ -79,36 +73,21 @@ public class MidiChordHelper {
                        addWindowListener(new WindowAdapter() {
                                @Override
                                public void windowClosing(WindowEvent event) {
-                                       if( ! applet.playlistModel.isModified() || applet.midiEditor.confirm(
+                                       if( ! applet.isModified() || applet.midiEditor.confirm(
                                                "MIDI file not saved, exit anyway ?\n"+
                                                "保存されていないMIDIファイルがありますが、終了してよろしいですか?"
-                                       )) {
-                                               applet.destroy();
-                                               System.exit(0);
-                                       }
+                                       )) { applet.destroy(); System.exit(0); }
                                }
                        });
-                       applet.sequencerModel.addChangeListener(new ChangeListener() {
-                               /**
-                                * シーケンサで切り替わった再生対象ファイル名をタイトルバーに反映
-                                */
-                               @Override
-                               public void stateChanged(ChangeEvent event) {
+                       // シーケンサで切り替わった再生対象ファイル名をタイトルバーに反映
+                       applet.sequencerModel.addChangeListener(e->setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel()));
+                       // プレイリスト上で変更された再生対象ファイル名をタイトルバーに反映
+                       applet.playlistModel.addTableModelListener(tme->{
+                               int col = tme.getColumn();
+                               if( col == PlaylistTableModel.Column.FILENAME.ordinal() || col == TableModelEvent.ALL_COLUMNS ) {
                                        setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel());
                                }
                        });
-                       applet.playlistModel.addTableModelListener(new TableModelListener() {
-                               /**
-                                * プレイリスト上で変更された再生対象ファイル名をタイトルバーに反映
-                                */
-                               @Override
-                               public void tableChanged(TableModelEvent event) {
-                                       int col = event.getColumn();
-                                       if( col == PlaylistTableModel.Column.FILENAME.ordinal() || col == TableModelEvent.ALL_COLUMNS ) {
-                                               setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel());
-                                       }
-                               }
-                       });
                        applet.midiEditor.loadAndPlay(fileList);
                }
                @Override
index ec1ed4f..0d11298 100644 (file)
@@ -8,8 +8,6 @@ import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.Stroke;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.geom.AffineTransform;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -206,25 +204,15 @@ public class AnoGakkiPane extends JComponent {
         */
        public AnoGakkiPane() {
                setOpaque(false);
-               timer = new Timer(
-                       INTERVAL_MS,
-                       new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent event) {
-                                       synchronized(queue) {
-                                               Iterator<QueueEntry> i = queue.iterator();
-                                               while( i.hasNext() )
-                                                       if( i.next().countDown() <= 0 )i.remove();
-                                       }
-                                       if(queue.isEmpty()) timer.stop();
-                                       repaint();
-                               }
-                       }
-               ) {
-                       {
-                               setCoalesce(true);
-                               setRepeats(true);
+               timer = new Timer(INTERVAL_MS, e->{
+                       synchronized(queue) {
+                               Iterator<QueueEntry> i = queue.iterator();
+                               while(i.hasNext()) if(i.next().countDown() <= 0) i.remove();
                        }
+                       if(queue.isEmpty()) timer.stop();
+                       repaint();
+               }) {
+                       {setCoalesce(true);setRepeats(true);}
                };
        }
        private Timer timer;
@@ -236,7 +224,7 @@ public class AnoGakkiPane extends JComponent {
                g2.setColor(color);
                synchronized(queue) {
                        Iterator<QueueEntry> i = queue.iterator();
-                       while( i.hasNext() ) {
+                       while(i.hasNext()) {
                                QueueEntry entry = i.next();
                                entry.shape.draw(g2, entry);
                        }
@@ -265,9 +253,7 @@ public class AnoGakkiPane extends JComponent {
                        return;
                }
                point = SwingUtilities.convertPoint(source, point, this);
-               synchronized (queue) {
-                       queue.add(new QueueEntry(point));
-               }
+               synchronized (queue) { queue.add(new QueueEntry(point)); }
                timer.start();
                prevStartedAt = startedAt;
        }
index 59a2001..57a75b8 100644 (file)
@@ -1,8 +1,5 @@
 package camidion.chordhelper.chorddiagram;
 
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-
 import javax.swing.BoxLayout;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -27,12 +24,7 @@ public class CapoSelecterView extends JPanel {
         * カポ選択ビューを構築します。
         */
        public CapoSelecterView() {
-               checkbox.addItemListener(new ItemListener() {
-                       @Override
-                       public void itemStateChanged(ItemEvent e) {
-                               valueSelecter.setVisible(checkbox.isSelected());
-                       }
-               });
+               checkbox.addItemListener(e->valueSelecter.setVisible(checkbox.isSelected()));
                setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
                add(checkbox);
                add(valueSelecter);
index 36500c3..a852cfa 100644 (file)
@@ -2,12 +2,6 @@ package camidion.chordhelper.chorddiagram;
 import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.AdjustmentEvent;
-import java.awt.event.AdjustmentListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumMap;
@@ -108,8 +102,7 @@ public class ChordDiagram extends JPanel {
                                                add(new JPanel() {
                                                        {
                                                                setOpaque(false);
-                                                               for(JRadioButton rb : instButtons.values())
-                                                                       add(rb);
+                                                               for(JRadioButton rb : instButtons.values()) add(rb);
                                                                setAlignmentY((float)1.0);
                                                        }
                                                });
@@ -164,12 +157,7 @@ public class ChordDiagram extends JPanel {
                                        JRadioButton radioButton = new JRadioButton(label) {
                                                {
                                                        setOpaque(false);
-                                                       addActionListener(new ActionListener() {
-                                                               @Override
-                                                               public void actionPerformed(ActionEvent e) {
-                                                                       diagramDisplay.tune(instrument);
-                                                               }
-                                                       });
+                                                       addActionListener(e->diagramDisplay.tune(instrument));
                                                }
                                        };
                                        buttonGroup.add(radioButton);
@@ -182,14 +170,7 @@ public class ChordDiagram extends JPanel {
        private JScrollBar variationScrollbar = new JScrollBar(JScrollBar.VERTICAL) {
                {
                        setModel(diagramDisplay.chordVariations.indexModel);
-                       addAdjustmentListener(
-                               new AdjustmentListener() {
-                                       @Override
-                                       public void adjustmentValueChanged(AdjustmentEvent e) {
-                                               setToolTipText(diagramDisplay.chordVariations.getIndexDescription());
-                                       }
-                               }
-                       );
+                       addAdjustmentListener(e->setToolTipText(diagramDisplay.chordVariations.getIndexDescription()));
                }
        };
        private JScrollBar fretRangeScrollbar = new JScrollBar(JScrollBar.HORIZONTAL) {
@@ -202,12 +183,7 @@ public class ChordDiagram extends JPanel {
         * カポ位置選択コンボボックス
         */
        public CapoSelecterView capoSelecterView = new CapoSelecterView() {
-               {
-                       checkbox.addItemListener(new ItemListener() {
-                               @Override
-                               public void itemStateChanged(ItemEvent e) { clear(); }
-                       });
-               }
+               { checkbox.addItemListener(e->clear()); }
        };
        @Override
        public void setBackground(Color bgColor) {
index c53cd1b..be8345a 100644 (file)
@@ -16,8 +16,6 @@ import java.util.LinkedList;
 
 import javax.swing.DefaultBoundedRangeModel;
 import javax.swing.JComponent;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 
 import camidion.chordhelper.chorddiagram.ChordDiagram.Instrument;
 import camidion.chordhelper.music.Chord;
@@ -200,9 +198,7 @@ class ChordDiagramDisplay extends JComponent implements MouseListener, MouseMoti
                                        fretIndex++
                                ) {
                                        if( fretIndex == 0 || fretIndex > fretViewIndexModel.getValue() ) {
-                                               int chordNoteIndex = chord.indexOf(
-                                                       notesWhenOpen[stringIndex]+fretIndex
-                                               );
+                                               int chordNoteIndex = chord.indexOf(notesWhenOpen[stringIndex]+fretIndex);
                                                if( chordNoteIndex >= 0 ) {
                                                        possiblePressingPoints[stringIndex].add(
                                                                new PressingPoint(fretIndex,chordNoteIndex,stringIndex)
@@ -305,30 +301,13 @@ class ChordDiagramDisplay extends JComponent implements MouseListener, MouseMoti
        public ChordDiagramDisplay(ChordDiagram.Instrument inst) {
                addMouseListener(this);
                addMouseMotionListener(this);
-               addComponentListener(
-                       new ComponentAdapter() {
-                               @Override
-                               public void componentResized(ComponentEvent e) {
-                                       tune();
-                               }
-                       }
-               );
-               chordVariations.indexModel.addChangeListener(
-                       new ChangeListener() {
-                               @Override
-                               public void stateChanged(ChangeEvent e) {
-                                       repaint();
-                               }
-                       }
-               );
-               fretViewIndexModel.addChangeListener(
-                       new ChangeListener() {
-                               @Override
-                               public void stateChanged(ChangeEvent e) {
-                                       setChord(); // To reconstruct chord variations
-                               }
-                       }
-               );
+               addComponentListener(new ComponentAdapter() {
+                       @Override
+                       public void componentResized(ComponentEvent e) { tune(); }
+               });
+               chordVariations.indexModel.addChangeListener(e->repaint());
+               // To reconstruct chord variations
+               fretViewIndexModel.addChangeListener(e->setChord());
                setMinimumSize(new Dimension(100,70));
                tune(inst);
        }
@@ -438,9 +417,7 @@ class ChordDiagramDisplay extends JComponent implements MouseListener, MouseMoti
                        }
                }
        }
-       private void drawIndicator(
-               Graphics2D g2, PressingPoint pp, boolean drawAllPoints
-       ) {
+       private void drawIndicator(Graphics2D g2, PressingPoint pp, boolean drawAllPoints) {
                Rectangle r;
                int i_chord = pp.chordNoteIndex;
                g2.setColor(
index 43adf8f..5565259 100644 (file)
@@ -11,8 +11,6 @@ import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.dnd.DragSource;
-import java.awt.dnd.DragSourceDragEvent;
-import java.awt.dnd.DragSourceMotionListener;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.awt.event.ComponentListener;
@@ -20,7 +18,6 @@ import java.util.Arrays;
 import java.util.Hashtable;
 import java.util.List;
 
-import javax.sound.midi.MidiDevice;
 import javax.sound.midi.Receiver;
 import javax.sound.midi.Transmitter;
 import javax.swing.JComponent;
@@ -129,13 +126,10 @@ public class MidiCablePane extends JComponent {
                public void internalFrameDeactivated(InternalFrameEvent e) { repaint(); }
                @Override
                public void internalFrameClosing(InternalFrameEvent e) {
-                       JInternalFrame frame = e.getInternalFrame();
-                       if( ! (frame instanceof MidiDeviceFrame) ) return;
-                       MidiDeviceFrame f = (MidiDeviceFrame)frame;
-                       MidiDeviceModel m = f.getMidiDeviceModel();
-                       MidiDevice d = m.getMidiDevice();
-                       List<Receiver> rxList = d.getReceivers();
-                       for( Receiver rx : rxList ) rxToColor.remove(rx);
+                       JInternalFrame f = e.getInternalFrame();
+                       if( ! (f instanceof MidiDeviceFrame) ) return;
+                       MidiDeviceModel m = ((MidiDeviceFrame)f).getMidiDeviceModel();
+                       m.getMidiDevice().getReceivers().forEach(rx->rxToColor.remove(rx));
                        repaint();
                }
        };
@@ -157,14 +151,11 @@ public class MidiCablePane extends JComponent {
                this.desktopPane = desktopPane;
                setOpaque(false);
                setVisible(true);
-               DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
-                       @Override
-                   public void dragMouseMoved(DragSourceDragEvent dsde) {
-                               // OSのスクリーン座標系から、このケーブル画面の座標系に変換する
-                       Point origin = getLocationOnScreen();
-                       (draggingLocation = dsde.getLocation()).translate(-origin.x, -origin.y);
-                       repaint();
-                   }
+               DragSource.getDefaultDragSource().addDragSourceMotionListener(dsde->{
+                       // OSのスクリーン座標系から、このケーブル画面の座標系に変換する
+               Point origin = getLocationOnScreen();
+               (draggingLocation = dsde.getLocation()).translate(-origin.x, -origin.y);
+               repaint();
                });
        }
 
index 045b772..296e0aa 100644 (file)
@@ -4,10 +4,9 @@ import java.awt.datatransfer.DataFlavor;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.beans.PropertyVetoException;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.sound.midi.MidiUnavailableException;
 import javax.swing.JDesktopPane;
@@ -98,29 +97,22 @@ public class MidiDeviceDesktopPane extends JDesktopPane implements TreeSelection
                        public void treeNodesRemoved(TreeModelEvent e) { }
                        @Override
                        public void treeStructureChanged(TreeModelEvent e) {
+                               // USBから切断されてツリーから消滅したMIDIデバイスモデルのフレームを削除
+                               frameMap.keySet().stream().filter(m-> ! deviceTreeModel.contains(m))
+                                       .collect(Collectors.toList()).stream().map(m-> frameMap.remove(m))
+                                       .filter(f-> f != null).forEach(f-> remove(f));
                                //
-                               // 削除されたデバイスモデルに対するデバイスフレームをマップから外す
-                               List<MidiDeviceModel> deviceModelsToRemove = new ArrayList<>();
-                               for( MidiDeviceModel m : frameMap.keySet() ) {
-                                       if( ! deviceTreeModel.contains(m) ) deviceModelsToRemove.add(m);
-                               }
-                               for( MidiDeviceModel m : deviceModelsToRemove ) {
-                                       MidiDeviceFrame frame = frameMap.remove(m);
-                                       if( frame != null ) remove(frame);
-                               }
-                               //
-                               // 新しいデバイスモデルに対するデバイスフレームを生成してマップに登録
-                               for( MidiDeviceModel deviceModel : deviceTreeModel ) {
-                                       if( frameMap.containsKey(deviceModel) ) continue;
-                                       MidiDeviceFrame frame = new MidiDeviceFrame(deviceModel, cablePane);
-                                       frameMap.put(deviceModel, frame);
+                               // ツリーに追加されたMIDIデバイスモデルのフレームを生成
+                               deviceTreeModel.stream().filter(dm -> ! frameMap.containsKey(dm)).forEach(dm->{
+                                       MidiDeviceFrame frame = new MidiDeviceFrame(dm, cablePane);
+                                       frameMap.put(dm, frame);
                                        //
                                        // トランスミッタリストモデルが変化したときにMIDIケーブルを再描画
-                                       TransmitterListModel txListModel = deviceModel.getTransmitterListModel();
+                                       TransmitterListModel txListModel = dm.getTransmitterListModel();
                                        if( txListModel != null ) txListModel.addListDataListener(cablePane.midiConnecterListDataListener);
                                        //
                                        // レシーバリストモデルが変化したときにMIDIケーブルを再描画
-                                       ReceiverListModel rxListModel = deviceModel.getReceiverListModel();
+                                       ReceiverListModel rxListModel = dm.getReceiverListModel();
                                        if( rxListModel != null ) rxListModel.addListDataListener(cablePane.midiConnecterListDataListener);
                                        //
                                        // デバイスフレームが開閉したときの動作
@@ -132,14 +124,12 @@ public class MidiDeviceDesktopPane extends JDesktopPane implements TreeSelection
                                        frame.addComponentListener(cablePane.midiDeviceFrameComponentListener);
                                        //
                                        // サイズを設定したフレームをデスクトップに追加
-                                       frame.setSize(250, deviceModel.getInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
+                                       frame.setSize(250, dm.getInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
                                        add(frame);
                                        //
                                        // デバイスが開いていたら表示
-                                       if( deviceModel.getMidiDevice().isOpen() ) {
-                                               frame.setVisible(true);
-                                       }
-                               }
+                                       if( dm.getMidiDevice().isOpen() ) frame.setVisible(true);
+                               });
                        }
                };
                deviceTreeModel.addTreeModelListener(treeModelListener);
index 353bcc4..09cfc0e 100644 (file)
@@ -1,7 +1,6 @@
 package camidion.chordhelper.mididevice;
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
@@ -30,9 +29,7 @@ public class MidiDeviceDialog extends JDialog {
                        putValue(LARGE_ICON_KEY, MIDI_CONNECTER_ICON);
                }
                @Override
-               public void actionPerformed(ActionEvent event) {
-                       setVisible(true);
-               }
+               public void actionPerformed(ActionEvent event) { setVisible(true); }
        };
        /**
         * MIDIデバイスダイアログを構築します。
@@ -56,22 +53,14 @@ public class MidiDeviceDialog extends JDialog {
                                        add(new JPanel() {{
                                                add(new JButton("Detect USB MIDI devices", new ButtonIcon(ButtonIcon.REPEAT_ICON)) {{
                                                        setToolTipText("Update view for USB MIDI device newly plugged or removed");
-                                                       addActionListener(new ActionListener() {
-                                                               @Override
-                                                               public void actionPerformed(ActionEvent e) {
-                                                                       deviceTreeModel.updateMidiDeviceList();
-                                                                       deviceTreeView.expandAll();
-                                                               }
+                                                       addActionListener(e->{
+                                                               deviceTreeModel.updateMidiDeviceList();
+                                                               deviceTreeView.expandAll();
                                                        });
                                                }});
                                                add(new JButton("Reset Tx timestamp", new ButtonIcon(ButtonIcon.TOP_ICON)) {{
                                                        setToolTipText("Reset timestamp on transmittable MIDI devices");
-                                                       addActionListener(new ActionListener() {
-                                                               @Override
-                                                               public void actionPerformed(ActionEvent e) {
-                                                                       deviceTreeModel.resetMicrosecondPosition();
-                                                               }
-                                                       });
+                                                       addActionListener(e->deviceTreeModel.resetMicrosecondPosition());
                                                }});
                                                setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
                                        }});
index 1ba0014..cb34f0c 100644 (file)
@@ -31,6 +31,11 @@ public enum MidiDeviceInOutType {
                this.description = description;
                this.shortName = shortName;
        }
+       /**
+        * 指定されたMIDIデバイスがどの入出力タイプに該当するかを返します。
+        * @param device MIDIデバイス
+        * @return 指定されたMIDIデバイスに対する入出力タイプ
+        */
        public static MidiDeviceInOutType getValueFor(MidiDevice device) {
                // tx:IN rx:OUT
                return device.getMaxReceivers() == 0 ?
index 2411c8e..ec2729f 100644 (file)
@@ -1,5 +1,6 @@
 package camidion.chordhelper.mididevice;
 
+import java.util.AbstractCollection;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -10,6 +11,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
+import java.util.stream.Collectors;
 
 import javax.sound.midi.MidiDevice;
 import javax.sound.midi.MidiSystem;
@@ -41,6 +43,9 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
        public int size() { return deviceModelList.size(); }
        @Override
        public MidiDeviceModel get(int index) { return deviceModelList.get(index); }
+       /**
+        * このリストの内容を反映したツリー構造のマップ
+        */
        protected Map<MidiDeviceInOutType, List<MidiDeviceModel>> deviceModelTree; {
                deviceModelTree = new EnumMap<>(MidiDeviceInOutType.class);
                deviceModelTree.put(MidiDeviceInOutType.MIDI_OUT, new ArrayList<>());
@@ -48,9 +53,11 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                deviceModelTree.put(MidiDeviceInOutType.MIDI_IN_OUT, new ArrayList<>());
        };
        /**
-        * {@link #add()}の非public版です。
+        * {@link AbstractList#add(E)}の操作を内部的に行います。
+        * 指定された要素をこのリストの最後に追加し、ツリー構造にも反映します。
+        *
         * @param dm 追加するMIDIデバイスモデル
-        * @return true({@link AbstractList#add()}ã\81¨å\90\8cã\81\98ï¼\89
+        * @return true({@link AbstractList#add(E)} ã\81¨å\90\8cæ§\98ï¼\89
         */
        protected boolean addInternally(MidiDeviceModel dm) {
                if( ! deviceModelList.add(dm) ) return false;
@@ -58,21 +65,18 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                return true;
        }
        /**
-        * {@link #removeAll()}の非public版です。
+        * {@link AbstractCollection#removeAll(Collection)}の操作を内部的に行います。
+        * 指定されたコレクションに該当するすべての要素を、このリストから削除します。
+        * このリストが変更された場合、ツリー構造にも反映されます。
         * @param c 削除する要素のコレクション
-        * @return {@link AbstractList#removeAll()}と同じ
+        * @return このリストが変更された場合はtrue({@link AbstractCollection#removeAll(Collection)} と同様)
         */
        protected boolean removeAllInternally(Collection<?> c) {
                if( ! deviceModelList.removeAll(c) ) return false;
-               for( Object o : c ) {
-                       if( o instanceof MidiDeviceModel ) {
-                               MidiDeviceInOutType ioType = ((MidiDeviceModel)o).getInOutType();
-                               deviceModelTree.get(ioType).remove(o);
-                       }
-               }
+               c.stream().filter(o -> o instanceof MidiDeviceModel).map(o -> (MidiDeviceModel)o)
+                       .forEach(mdm -> deviceModelTree.get(mdm.getInOutType()).remove(mdm));
                return true;
        }
-       // ツリーモデル用インターフェース
        @Override
        public Object getRoot() { return this; }
        @Override
@@ -120,7 +124,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
        }
 
        /**
-        * {@link MidiSystem#getMidiDeviceInfo()} ã\81®çµ\90æ\9e\9cã\82\92ã\80\81不変の {@link List} として返します。
+        * {@link MidiSystem#getMidiDeviceInfo()} ã\81\8cè¿\94ã\81\97ã\81\9fé\85\8då\88\97ã\82\92不変の {@link List} として返します。
         *
         * <p>注意点:MIDIデバイスをUSBから抜いて、他のデバイスとの接続を切断せずに
         * {@link MidiSystem#getMidiDeviceInfo()}を呼び出すと
@@ -146,27 +150,31 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * @param guiVirtualDevice 管理対象に含めるGUI仮想MIDIデバイス
         */
        public MidiDeviceTreeModel(VirtualMidiDevice guiVirtualDevice) {
+               MidiDeviceModel synthModel = null;
+               MidiDeviceModel firstMidiInModel = null;
+               MidiDeviceModel firstMidiOutModel = null;
+               // GUI
                MidiDeviceModel guiModel = new MidiDeviceModel(guiVirtualDevice, this);
                addInternally(guiModel);
+               // シーケンサー
                try {
                        addInternally(sequencerModel = new MidiSequencerModel(MidiSystem.getSequencer(false), this));
                } catch( MidiUnavailableException e ) {
                        System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
                        e.printStackTrace();
                }
-               MidiDeviceModel synthModel = null;
-               MidiDeviceModel firstMidiInModel = null;
-               MidiDeviceModel firstMidiOutModel = null;
-               for( MidiDevice.Info info : getMidiDeviceInfo() ) {
-                       MidiDevice device;
+               // システムで使用可能な全MIDIデバイス(シーケンサーはすでに取得済みなので除外)
+               for( MidiDevice device : getMidiDeviceInfo().stream().map(info -> {
                        try {
-                               device = MidiSystem.getMidiDevice(info);
+                               return MidiSystem.getMidiDevice(info);
                        } catch( MidiUnavailableException e ) {
                                e.printStackTrace();
-                               continue;
+                               return null;
                        }
-                       if( device instanceof Sequencer ) continue; // シーケンサはすでに取得済み
-                       if( device instanceof Synthesizer ) { // Java内蔵シンセサイザ
+               }).filter(
+                       device -> device != null && ! (device instanceof Sequencer)
+               ).collect(Collectors.toList()) ) {
+                       if( device instanceof Synthesizer ) { // Java内蔵シンセサイザの場合
                                try {
                                        addInternally(synthModel = new MidiDeviceModel(MidiSystem.getSynthesizer(), this));
                                } catch( MidiUnavailableException e ) {
@@ -197,38 +205,36 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                //   開く順序が逆になると「進みすぎるから遅らせよう」として無用なレイテンシーが発生する原因になる。
                //
                List<MidiDeviceModel> openedMidiDeviceModelList = new ArrayList<>();
-               for( MidiDeviceModel toOpen : Arrays.asList(
-                               synthModel, firstMidiOutModel, sequencerModel, guiModel, firstMidiInModel) ) {
-                       if( toOpen == null ) continue;
+               Arrays.asList(
+                       synthModel,
+                       firstMidiOutModel,
+                       sequencerModel,
+                       guiModel,
+                       firstMidiInModel
+               ).stream().filter(mdm -> mdm != null).forEach(mdm->{
                        try {
-                               toOpen.open();
+                               mdm.open();
+                               openedMidiDeviceModelList.add(mdm);
                        } catch( MidiUnavailableException ex ) {
                                String title = ChordHelperApplet.VersionInfo.NAME;
-                               String message = "Cannot open MIDI device '"+toOpen+"'\n"
-                                               + "MIDIデバイス "+toOpen+" を開くことができません。\n\n"
-                                               + ex.getMessage();
+                               String message = "Cannot open MIDI device '"+mdm+"'\n"
+                                               + "MIDIデバイス "+mdm+" を開くことができません。\n\n" + ex;
                                JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
-                               continue;
                        }
-                       openedMidiDeviceModelList.add(toOpen);
-               }
+               });
                // 初期接続マップを作成(開いたデバイスを相互に接続する)
+               // 自身のTx/Rx同士の接続は、シーケンサーモデルはなし、それ以外(GUIデバイスモデル)はあり。
                Map<MidiDeviceModel, Collection<MidiDeviceModel>> initialConnection = new LinkedHashMap<>();
-               for( MidiDeviceModel rxm : openedMidiDeviceModelList ) {
-                       if( rxm.getReceiverListModel() == null ) continue;
+               openedMidiDeviceModelList.stream().filter(rxm ->
+                       rxm.getReceiverListModel() != null
+               ).forEach(rxm -> {
                        List<MidiDeviceModel> txmList;
                        initialConnection.put(rxm, txmList = new ArrayList<>());
-                       for( MidiDeviceModel txm : openedMidiDeviceModelList ) {
-                               if( txm.getTransmitterListModel() == null ) continue;
-                               //
-                               // Tx/Rx両方を持つデバイスでは
-                               // ・シーケンサーモデルは自分自身には接続しない
-                               // ・GUIデバイスモデルでは自分自身にも接続する
-                               if( txm == sequencerModel && txm == rxm ) continue;
-                               //
-                               txmList.add(txm);
-                       }
-               }
+                       openedMidiDeviceModelList.stream().filter(txm ->
+                               txm.getTransmitterListModel() != null
+                               && !(txm == sequencerModel && txm == rxm)
+                       ).forEach(txm -> txmList.add(txm));
+               });
                // 初期接続を実行
                connectDevices(initialConnection);
        }
@@ -236,7 +242,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * すべてのMIDIデバイスを閉じます。
         */
        public void closeAllDevices() {
-               for(MidiDeviceModel m : deviceModelList) m.getMidiDevice().close();
+               deviceModelList.forEach(m -> m.getMidiDevice().close());
        }
        /**
         * デバイス間の接続をすべて切断します。
@@ -251,13 +257,12 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         */
        public Map<MidiDeviceModel, Collection<MidiDeviceModel>> disconnectAllDevices() {
                Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections = new LinkedHashMap<>();
-               for(MidiDeviceModel m : deviceModelList) {
+               deviceModelList.stream().forEach(m -> {
                        ReceiverListModel rxListModel = m.getReceiverListModel();
-                       if( rxListModel == null ) continue;
+                       if( rxListModel == null ) return;
                        Collection<MidiDeviceModel> txDeviceModels = rxListModel.closeTransmitters();
-                       if( txDeviceModels.isEmpty() ) continue;
-                       rxToTxConnections.put(m, txDeviceModels);
-               }
+                       if( ! txDeviceModels.isEmpty() ) rxToTxConnections.put(m, txDeviceModels);
+               });
                return rxToTxConnections;
        }
        /**
@@ -270,18 +275,16 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * </ul>
         */
        public void connectDevices(Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections) {
-               for( MidiDeviceModel rxm : rxToTxConnections.keySet() ) {
-                       if( rxm == null ) continue;
+               rxToTxConnections.keySet().stream().filter(rxm -> rxm != null).forEach(rxm -> {
                        Receiver rx = rxm.getReceiverListModel().getTransceivers().get(0);
-                       for( MidiDeviceModel txm : rxToTxConnections.get(rxm) ) {
-                               if( txm == null ) continue;
+                       rxToTxConnections.get(rxm).stream().filter(txm -> txm != null).forEach(txm -> {
                                try {
                                        txm.getTransmitterListModel().openTransmitter().setReceiver(rx);
                                } catch( MidiUnavailableException e ) {
                                        e.printStackTrace();
                                }
-                       }
-               }
+                       });
+               });
        }
        /**
         * USB-MIDIデバイスの着脱後、MIDIデバイスリストを最新の状態に更新します。
@@ -297,27 +300,25 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                //
                // 追加・削除されたMIDIデバイスを特定
                List<MidiDevice.Info> toAdd = new Vector<>(getMidiDeviceInfo());
-               List<MidiDeviceModel> toRemove = new Vector<>();
-               for(MidiDeviceModel m : deviceModelList) {
+               List<MidiDeviceModel> toRemove = deviceModelList.stream().filter(m -> {
                        MidiDevice d = m.getMidiDevice();
-                       if( d instanceof VirtualMidiDevice || toAdd.remove(d.getDeviceInfo()) ) continue;
-                       d.close();
-                       toRemove.add(m);
-               }
+                       if( d instanceof VirtualMidiDevice || toAdd.remove(d.getDeviceInfo()) ) return false;
+                       d.close(); return true;
+               }).collect(Collectors.toList());
                // 削除されたデバイスのモデルを除去
                if( removeAllInternally(toRemove) ) {
                        Set<MidiDeviceModel> rxModels = rxToTxConnections.keySet();
                        rxModels.removeAll(toRemove);
-                       for( MidiDeviceModel m : rxModels ) rxToTxConnections.get(m).removeAll(toRemove);
+                       rxModels.forEach(m -> rxToTxConnections.get(m).removeAll(toRemove));
                }
                // 追加されたデバイスのモデルを登録
-               for( MidiDevice.Info info : toAdd ) {
+               toAdd.forEach(info -> {
                        try {
                                addInternally(new MidiDeviceModel(info, this));
                        } catch( MidiUnavailableException e ) {
                                e.printStackTrace();
                        }
-               }
+               });
                // 再接続
                connectDevices(rxToTxConnections);
                //
@@ -329,10 +330,9 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * {@link MidiDeviceModel#resetMicrosecondPosition()}でマイクロ秒位置をリセットします。
         */
        public void resetMicrosecondPosition() {
-               for(MidiDeviceModel m : deviceModelList) {
-                       TransmitterListModel txListModel = m.getTransmitterListModel();
-                       if( txListModel != null ) txListModel.resetMicrosecondPosition();
-               }
+               deviceModelList.stream().map(dm -> dm.getTransmitterListModel())
+                       .filter(tlm -> tlm != null)
+                       .forEach(tlm -> tlm.resetMicrosecondPosition());
        }
 
 }
index 9b5d273..de0050c 100644 (file)
@@ -1,7 +1,6 @@
 package camidion.chordhelper.mididevice;
 
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -27,7 +26,7 @@ import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
 import camidion.chordhelper.midieditor.SequencerSpeedSlider;
 
 /**
- * MIDIシーケンサモデル
+ * MIDIシーケンサモデル(再生位置モデルのインターフェース付き)
  */
 public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeModel {
        /**
@@ -43,15 +42,10 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
                super(sequencer, deviceModelTree);
        }
        /**
-        * このシーケンサーの再生スピード調整モデル
+        * このシーケンサーの再生スピード
         */
        public BoundedRangeModel speedSliderModel = new DefaultBoundedRangeModel(0, 0, -7, 7) {{
-               addChangeListener(new ChangeListener() {
-                       @Override
-                       public void stateChanged(ChangeEvent e) {
-                               getSequencer().setTempoFactor(SequencerSpeedSlider.tempoFactorOf(getValue()));
-                       }
-               });
+               addChangeListener(e->getSequencer().setTempoFactor(SequencerSpeedSlider.tempoFactorOf(getValue())));
        }};
        /**
         * MIDIシーケンサを返します。
@@ -61,11 +55,9 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
        /**
         * 開始終了アクション
         */
-       public StartStopAction startStopAction = new StartStopAction();
-       /**
-        * 開始終了アクション
-        */
-       class StartStopAction extends AbstractAction {
+       public Action getStartStopAction() { return startStopAction; }
+       private StartStopAction startStopAction = new StartStopAction();
+       private class StartStopAction extends AbstractAction {
                private Map<Boolean,Icon> iconMap = new HashMap<Boolean,Icon>() {
                        {
                                put(Boolean.FALSE, new ButtonIcon(ButtonIcon.PLAY_ICON));
@@ -73,43 +65,19 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
                        }
                };
                {
-                       putValue(
-                               SHORT_DESCRIPTION,
-                               "Start/Stop recording or playing - 録音または再生の開始/停止"
-                       );
+                       putValue(SHORT_DESCRIPTION, "Start/Stop recording or playing - 録音または再生の開始/停止");
                        setRunning(false);
                }
                @Override
                public void actionPerformed(ActionEvent event) {
                        if(timeRangeUpdater.isRunning()) stop(); else start();
                }
-               /**
-                * 開始されているかどうかを設定します。
-                * @param isRunning 開始されていたらtrue
-                */
                private void setRunning(boolean isRunning) {
                        putValue(LARGE_ICON_KEY, iconMap.get(isRunning));
                        putValue(SELECTED_KEY, isRunning);
                }
        }
        /**
-        * シーケンサに合わせてミリ秒位置を更新するタイマー
-        */
-       private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer( 20,
-               new ActionListener(){
-                       @Override
-                       public void actionPerformed(ActionEvent e) {
-                               if( valueIsAdjusting || ! getSequencer().isRunning() ) {
-                                       // 手動で移動中の場合や、シーケンサが止まっている場合は、
-                                       // タイマーによる更新は不要
-                                       return;
-                               }
-                               // リスナーに読み込みを促す
-                               fireStateChanged();
-                       }
-               }
-       );
-       /**
         * このモデルのMIDIシーケンサを開始します。
         *
         * <p>録音するMIDIチャンネルがMIDIエディタで指定されている場合、
@@ -198,6 +166,18 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
        public void setValueIsAdjusting(boolean valueIsAdjusting) {
                this.valueIsAdjusting = valueIsAdjusting;
        }
+       /**
+        * シーケンサに合わせてミリ秒位置を更新するタイマー
+        */
+       private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer(20, e->{
+               if( valueIsAdjusting || ! getSequencer().isRunning() ) {
+                       // 手動で移動中の場合や、シーケンサが止まっている場合は、
+                       // タイマーによる更新は不要
+                       return;
+               }
+               // リスナーに読み込みを促す
+               fireStateChanged();
+       });
        @Override
        public void setRangeProperties(int value, int extent, int min, int max, boolean valueIsAdjusting) {
                getSequencer().setMicrosecondPosition(RESOLUTION_MICROSECOND * (long)value);
@@ -301,7 +281,8 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
        /**
         * 1小節戻るアクション
         */
-       public Action moveBackwardAction = new AbstractAction() {
+       public Action getMoveBackwardAction() { return moveBackwardAction; }
+       private Action moveBackwardAction = new AbstractAction() {
                {
                        putValue(SHORT_DESCRIPTION, "Move backward 1 measure - 1小節戻る");
                        putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BACKWARD_ICON));
@@ -312,7 +293,8 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
        /**
         *1小節進むアクション
         */
-       public Action moveForwardAction = new AbstractAction() {
+       public Action getMoveForwardAction() { return moveForwardAction; }
+       private Action moveForwardAction = new AbstractAction() {
                {
                        putValue(SHORT_DESCRIPTION, "Move forward 1 measure - 1小節進む");
                        putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.FORWARD_ICON));
index 69f72cc..6ea8550 100644 (file)
@@ -6,8 +6,6 @@ import javax.sound.midi.Sequencer;
 import javax.swing.BoxLayout;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 
 import camidion.chordhelper.midieditor.SequenceTickIndex;
 import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
@@ -26,38 +24,35 @@ public class SequencerMeasureView extends JPanel {
                setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
                add(measurePositionLabel = new MeasurePositionLabel());
                add(measureLengthLabel = new MeasureLengthLabel());
-               model.addChangeListener(new ChangeListener() {
-                       @Override
-                       public void stateChanged(ChangeEvent e) {
-                               Object source = e.getSource();
-                               if( ! (source instanceof MidiSequencerModel) ) return;
-                               MidiSequencerModel model = (MidiSequencerModel)source;
-                               Sequencer sequencer = model.getSequencer();
-                               SequenceTrackListTableModel sequenceTableModel = model.getSequenceTrackListTableModel();
-                               SequenceTickIndex tickIndex = (
-                                       sequenceTableModel == null ? null : sequenceTableModel.getSequenceTickIndex()
-                               );
-                               if( ! sequencer.isRunning() || sequencer.isRecording() ) {
-                                       // 停止中または録音中の場合、長さが変わることがあるので表示を更新
-                                       if( tickIndex == null ) {
-                                               measureLengthLabel.setMeasure(0);
-                                       }
-                                       else {
-                                               long tickLength = sequencer.getTickLength();
-                                               int measureLength = tickIndex.tickToMeasure(tickLength);
-                                               measureLengthLabel.setMeasure(measureLength);
-                                       }
-                               }
-                               // 小節位置の表示を更新
+               model.addChangeListener(e -> {
+                       Object source = e.getSource();
+                       if( ! (source instanceof MidiSequencerModel) ) return;
+                       MidiSequencerModel sourceModel = (MidiSequencerModel)source;
+                       Sequencer sequencer = sourceModel.getSequencer();
+                       SequenceTrackListTableModel sequenceTableModel = sourceModel.getSequenceTrackListTableModel();
+                       SequenceTickIndex tickIndex = (
+                               sequenceTableModel == null ? null : sequenceTableModel.getSequenceTickIndex()
+                       );
+                       if( ! sequencer.isRunning() || sequencer.isRecording() ) {
+                               // 停止中または録音中の場合、長さが変わることがあるので表示を更新
                                if( tickIndex == null ) {
-                                       measurePositionLabel.setMeasure(0, 0);
+                                       measureLengthLabel.setMeasure(0);
                                }
                                else {
-                                       long tickPosition = sequencer.getTickPosition();
-                                       int measurePosition = tickIndex.tickToMeasure(tickPosition);
-                                       measurePositionLabel.setMeasure(measurePosition, tickIndex.lastBeat);
+                                       long tickLength = sequencer.getTickLength();
+                                       int measureLength = tickIndex.tickToMeasure(tickLength);
+                                       measureLengthLabel.setMeasure(measureLength);
                                }
                        }
+                       // 小節位置の表示を更新
+                       if( tickIndex == null ) {
+                               measurePositionLabel.setMeasure(0, 0);
+                       }
+                       else {
+                               long tickPosition = sequencer.getTickPosition();
+                               int measurePosition = tickIndex.tickToMeasure(tickPosition);
+                               measurePositionLabel.setMeasure(measurePosition, tickIndex.lastBeat);
+                       }
                });
        }
        private static abstract class MeasureLabel extends JLabel {
@@ -77,8 +72,7 @@ public class SequencerMeasureView extends JPanel {
                        setToolTipText("Measure:beat position - 何小節目:何拍目");
                }
                public boolean setMeasure(int measure, int beat) {
-                       if( ! super.setMeasure(measure) && this.beat == beat )
-                               return false;
+                       if( ! super.setMeasure(measure) && this.beat == beat ) return false;
                        setText(String.format("%04d:%02d", measure+1, beat+1));
                        return true;
                }
@@ -89,8 +83,7 @@ public class SequencerMeasureView extends JPanel {
                        setToolTipText("Measure length - 小節の数");
                }
                public boolean setMeasure(int measure) {
-                       if( ! super.setMeasure(measure) )
-                               return false;
+                       if( ! super.setMeasure(measure) ) return false;
                        setText(String.format("/%04d", measure));
                        return true;
                }
index 5083469..1e33cd8 100644 (file)
@@ -43,14 +43,12 @@ public class Base64Dialog extends JDialog implements DocumentListener {
                        try {
                                midiData = getMIDIData();
                        } catch(Exception e) {
-                               e.printStackTrace();
                                error("Base64デコードに失敗しました。\n"+e);
                                return;
                        }
                        try {
                                midiEditor.sequenceListTable.getModel().addSequence(midiData, null);
                        } catch(Exception e) {
-                               e.printStackTrace();
                                error("Base64デコードされたデータが正しいMIDI形式になっていません。\n"+e);
                                return;
                        }
index d9a21e4..8c9f630 100644 (file)
@@ -12,9 +12,8 @@ public class KeySignatureLabel extends JLabel {
        private Key key;
        public KeySignatureLabel() { clear(); }
        public Key getKey() { return key; }
-       public void setKeySignature( Key key ) {
-               this.key = key;
-               if( key == null ) {
+       public void setKey(Key key) {
+               if( (this.key = key) == null ) {
                        setText("Key:C");
                        setToolTipText("Key: Unknown");
                        setEnabled(false);
@@ -28,5 +27,5 @@ public class KeySignatureLabel extends JLabel {
                );
                setEnabled(true);
        }
-       public void clear() { setKeySignature( (Key)null ); }
+       public void clear() { setKey((Key)null); }
 }
\ No newline at end of file
index 9dbc678..e52de08 100644 (file)
@@ -2,8 +2,6 @@ package camidion.chordhelper.midieditor;
 
 import java.awt.FlowLayout;
 import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 
 import javax.swing.Action;
 import javax.swing.JButton;
@@ -68,11 +66,7 @@ public class MidiEventDialog extends JDialog {
                        add(okButton = new JButton("OK"));
                        add(cancelButton = new JButton("Cancel"));
                }});
-               cancelButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               setVisible(false);
-                       }
-               });
+               cancelButton.addActionListener(e->setVisible(false));
        }
        public void openForm(
                String title, Action okAction, int midiChannel,
index 0025fff..918533e 100644 (file)
@@ -4,8 +4,6 @@ import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.InputEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.nio.charset.Charset;
 
 import javax.sound.midi.InvalidMidiDataException;
@@ -19,8 +17,6 @@ import javax.swing.ComboBoxModel;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JComboBox;
 import javax.swing.JPanel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 
 import camidion.chordhelper.music.Key;
 import camidion.chordhelper.music.MIDISpec;
@@ -152,19 +148,17 @@ public class MidiMessageForm extends JPanel implements ActionListener {
        private PianoKeyboardPanel keyboardPanel = new PianoKeyboardPanel() {
                {
                        keyboard.setPreferredSize(new Dimension(300,40));
-                       keyboard.addPianoKeyboardListener(
-                               new PianoKeyboardAdapter() {
-                                       public void pianoKeyPressed(int n, InputEvent e) {
-                                               data1Text.setValue(n);
-                                               if( midiChannels == null ) return;
-                                               midiChannels[channelText.getSelectedChannel()].noteOn(n, data2Text.getValue());
-                                       }
-                                       public void pianoKeyReleased(int n, InputEvent e) {
-                                               if( midiChannels == null ) return;
-                                               midiChannels[channelText.getSelectedChannel()].noteOff(n, data2Text.getValue());
-                                       }
+                       keyboard.addPianoKeyboardListener(new PianoKeyboardAdapter() {
+                               public void pianoKeyPressed(int n, InputEvent e) {
+                                       data1Text.setValue(n);
+                                       if( midiChannels == null ) return;
+                                       midiChannels[channelText.getSelectedChannel()].noteOn(n, data2Text.getValue());
                                }
-                       );
+                               public void pianoKeyReleased(int n, InputEvent e) {
+                                       if( midiChannels == null ) return;
+                                       midiChannels[channelText.getSelectedChannel()].noteOff(n, data2Text.getValue());
+                               }
+                       });
                }
        };
        /**
@@ -175,28 +169,15 @@ public class MidiMessageForm extends JPanel implements ActionListener {
         * テンポ選択
         */
        private TempoSelecter tempoSelecter = new TempoSelecter() {
-               {
-                       tempoSpinnerModel.addChangeListener(new ChangeListener() {
-                               @Override
-                               public void stateChanged(ChangeEvent e) {
-                                       dataText.setValue(getTempoByteArray());
-                               }
-                       });
-               }
+               { tempoSpinnerModel.addChangeListener(e->dataText.setValue(getTempoByteArray())); }
        };
        /**
         * 拍子選択
         */
        private TimeSignatureSelecter timesigSelecter = new TimeSignatureSelecter() {
                {
-                       upperTimesigModel.addChangeListener(new ChangeListener() {
-                               @Override
-                               public void stateChanged(ChangeEvent e) { update(); }
-                       });
-                       lowerTimesigView.addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) { update(); }
-                       });
+                       upperTimesigModel.addChangeListener(e->update());
+                       lowerTimesigView.addActionListener(e->update());
                }
                private void update() { dataText.setValue(getByteArray()); }
        };
@@ -205,14 +186,8 @@ public class MidiMessageForm extends JPanel implements ActionListener {
         */
        private KeySignatureSelecter keysigSelecter = new KeySignatureSelecter(new Key("C")) {
                {
-                       keysigCombobox.addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) { update(); }
-                       });
-                       minorCheckbox.addItemListener(new ItemListener() {
-                               @Override
-                               public void itemStateChanged(ItemEvent e) { update(); }
-                       });
+                       keysigCombobox.addActionListener(e->update());
+                       minorCheckbox.addItemListener(e->update());
                }
                private void update() { dataText.setValue(getSelectedKey().getBytes()); }
        };
index d78a0b4..8c16890 100644 (file)
@@ -10,8 +10,6 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.awt.event.ComponentListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -96,13 +94,13 @@ public class MidiSequenceEditorDialog extends JDialog {
         * エラーメッセージダイアログを表示します。
         * @param message エラーメッセージ
         */
-       public void showError(String message) { showMessage(message, JOptionPane.ERROR_MESSAGE); }
+       public void showError(Object message) { showMessage(message, JOptionPane.ERROR_MESSAGE); }
        /**
         * 警告メッセージダイアログを表示します。
         * @param message 警告メッセージ
         */
-       public void showWarning(String message) { showMessage(message, JOptionPane.WARNING_MESSAGE); }
-       private void showMessage(String message, int messageType) {
+       public void showWarning(Object message) { showMessage(message, JOptionPane.WARNING_MESSAGE); }
+       private void showMessage(Object message, int messageType) {
                JOptionPane.showMessageDialog(this, message, ChordHelperApplet.VersionInfo.NAME, messageType);
        }
        /**
@@ -110,7 +108,7 @@ public class MidiSequenceEditorDialog extends JDialog {
         * @param message 確認メッセージ
         * @return 確認OKのときtrue
         */
-       public boolean confirm(String message) {
+       public boolean confirm(Object message) {
                return JOptionPane.showConfirmDialog(this, message, ChordHelperApplet.VersionInfo.NAME,
                                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION ;
        }
@@ -129,11 +127,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                        try {
                                loadAndPlay((List<File>)support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));
                                return true;
-                       } catch (Exception e) {
-                               e.printStackTrace();
-                               showError(e.getMessage());
-                               return false;
-                       }
+                       } catch (Exception e) { showError(e); return false; }
                }
        };
 
@@ -151,10 +145,9 @@ public class MidiSequenceEditorDialog extends JDialog {
                try {
                        indexOfAddedTop = playlist.addSequences(fileList);
                } catch(IOException|InvalidMidiDataException e) {
-                       showWarning(e.getMessage());
+                       showWarning(e);
                } catch(AccessControlException e) {
-                       e.printStackTrace();
-                       showError(e.getMessage());
+                       showError(e);
                }
                MidiSequencerModel sequencerModel = playlist.getSequencerModel();
                if( sequencerModel.getSequencer().isRunning() ) {
@@ -165,11 +158,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                if( indexOfAddedTop >= 0 ) {
                        try {
                                playlist.loadToSequencer(indexOfAddedTop);
-                       } catch (InvalidMidiDataException ex) {
-                               ex.printStackTrace();
-                               showError(ex.getMessage());
-                               return;
-                       }
+                       } catch (InvalidMidiDataException e) { showError(e); return; }
                        sequencerModel.start();
                }
        }
@@ -284,7 +273,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                        //
                        // タイトルに合計シーケンス長を表示
                        if( lengthColumn != null ) {
-                               int sec = getModel().getTotalSeconds();
+                               int sec = getModel().getTotalTimeInSeconds();
                                String title = PlaylistTableModel.Column.LENGTH.title;
                                title = String.format(title+" [%02d:%02d]", sec/60, sec%60);
                                lengthColumn.setHeaderValue(title);
@@ -330,10 +319,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                        ) {
                                try {
                                        getModel().loadToSequencer(row);
-                               } catch (InvalidMidiDataException ex) {
-                                       ex.printStackTrace();
-                                       showError(ex.getMessage());
-                               }
+                               } catch (InvalidMidiDataException ex) { showError(ex); }
                                fireEditingStopped();
                                return null;
                        }
@@ -345,7 +331,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                        implements TableCellEditor, TableCellRenderer
                {
                        private JToggleButton playButton = new JToggleButton(
-                               getModel().getSequencerModel().startStopAction
+                               getModel().getSequencerModel().getStartStopAction()
                        ) {
                                { setMargin(ZERO_INSETS); }
                        };
@@ -380,17 +366,15 @@ public class MidiSequenceEditorDialog extends JDialog {
                                //
                                // セル内にプレイボタンがあれば、シングルクリックを受け付ける。
                                // プレイボタンのないセルは、ダブルクリックのみ受け付ける。
-                               return model.getSequenceList().get(row).isOnSequencer() || me.getClickCount() == 2;
+                               return model.getSequenceModelList().get(row).isOnSequencer() || me.getClickCount() == 2;
                        }
                        @Override
                        public Object getCellEditorValue() { return null; }
                        /**
                         * {@inheritDoc}
                         *
-                        * <p>この実装では、行の表すシーケンスが
-                        * シーケンサーにロードされている場合にプレイボタンを返します。
-                        * そうでない場合は、
-                        * そのシーケンスをシーケンサーにロードしてnullを返します。
+                        * <p>この実装では、行の表すシーケンスがシーケンサーにロードされている場合にプレイボタンを返します。
+                        * そうでない場合は、そのシーケンスをシーケンサーにロードしてnullを返します。
                         * </p>
                         */
                        @Override
@@ -399,13 +383,10 @@ public class MidiSequenceEditorDialog extends JDialog {
                        ) {
                                fireEditingStopped();
                                PlaylistTableModel model = getModel();
-                               if( model.getSequenceList().get(row).isOnSequencer() ) return playButton;
+                               if( model.getSequenceModelList().get(row).isOnSequencer() ) return playButton;
                                try {
                                        model.loadToSequencer(row);
-                               } catch (InvalidMidiDataException ex) {
-                                       ex.printStackTrace();
-                                       showError(ex.getMessage());
-                               }
+                               } catch (InvalidMidiDataException ex) { showError(ex); }
                                return null;
                        }
                        @Override
@@ -414,7 +395,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                                boolean hasFocus, int row, int column
                        ) {
                                PlaylistTableModel model = getModel();
-                               if(model.getSequenceList().get(row).isOnSequencer()) return playButton;
+                               if(model.getSequenceModelList().get(row).isOnSequencer()) return playButton;
                                Class<?> cc = model.getColumnClass(column);
                                TableCellRenderer defaultRenderer = table.getDefaultRenderer(cc);
                                return defaultRenderer.getTableCellRendererComponent(
@@ -428,7 +409,9 @@ public class MidiSequenceEditorDialog extends JDialog {
                 * @return プレイリストモデル
                 */
                @Override
-               public PlaylistTableModel getModel() { return (PlaylistTableModel)super.getModel(); }
+               public PlaylistTableModel getModel() {
+                       return (PlaylistTableModel)super.getModel();
+               }
                /**
                 * シーケンスを削除するアクション
                 */
@@ -450,8 +433,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                                try {
                                        model.removeSelectedSequence();
                                } catch (InvalidMidiDataException ex) {
-                                       ex.printStackTrace();
-                                       showError(ex.getMessage());
+                                       showError(ex);
                                }
                        }
                };
@@ -486,10 +468,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                                                sequenceModel.setModified(false);
                                                playlistModel.fireSequenceModified(sequenceModel, false);
                                        }
-                                       catch( IOException ex ) {
-                                               ex.printStackTrace();
-                                               showError( ex.getMessage() );
-                                       }
+                                       catch( IOException ex ) { showError(ex); }
                                }
                        };
                        /**
@@ -502,10 +481,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                                        if( showOpenDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return;
                                        try {
                                                loadAndPlay(getSelectedFile());
-                                       } catch (InvalidMidiDataException ex) {
-                                               ex.printStackTrace();
-                                               showError(ex.getMessage());
-                                       }
+                                       } catch (InvalidMidiDataException ex) { showError(ex); }
                                }
                        };
                };
@@ -789,11 +765,7 @@ public class MidiSequenceEditorDialog extends JDialog {
                private JToggleButton.ToggleButtonModel
                        pairNoteOnOffModel = new JToggleButton.ToggleButtonModel() {
                                {
-                                       addItemListener(new ItemListener() {
-                                               public void itemStateChanged(ItemEvent e) {
-                                                       eventDialog.midiMessageForm.durationForm.setEnabled(isSelected());
-                                               }
-                                       });
+                                       addItemListener(e->eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()));
                                        setSelected(true);
                                }
                        };
@@ -1158,9 +1130,9 @@ public class MidiSequenceEditorDialog extends JDialog {
                                }
                                add(Box.createRigidArea(new Dimension(5, 0)));
                                PlaylistTableModel playlistTableModel = sequenceListTable.getModel();
-                               add(new JButton(playlistTableModel.moveToTopAction) {{ setMargin(ZERO_INSETS); }});
+                               add(new JButton(playlistTableModel.getMoveToTopAction()) {{ setMargin(ZERO_INSETS); }});
                                add(Box.createRigidArea(new Dimension(5, 0)));
-                               add(new JButton(playlistTableModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }});
+                               add(new JButton(playlistTableModel.getMoveToBottomAction()) {{ setMargin(ZERO_INSETS); }});
                                if( sequenceListTable.midiFileChooser != null ) {
                                        add(Box.createRigidArea(new Dimension(5, 0)));
                                        add(new JButton(sequenceListTable.midiFileChooser.saveMidiFileAction) {
index fae7943..9d80da2 100644 (file)
@@ -106,7 +106,8 @@ public class NewSequenceDialog extends JDialog {
                @Override
                public void actionPerformed(ActionEvent event) {
                        try {
-                               playlist.addSequenceAndPlay(getMidiSequence());
+                               int index = playlist.addSequenceAndPlay(getMidiSequence());
+                               playlist.getSequenceModelList().get(index).setModified(true);
                        } catch (InvalidMidiDataException ex) {
                                ex.printStackTrace();
                                JOptionPane.showMessageDialog(
@@ -141,14 +142,7 @@ public class NewSequenceDialog extends JDialog {
                                }});
                                add(new JButton("Randomize (Tempo, Time signature, Chord progression)") {{
                                        setMargin(ZERO_INSETS);
-                                       addActionListener(new ActionListener() {
-                                               @Override
-                                               public void actionPerformed(ActionEvent e) {
-                                                       setRandomChordProgression(
-                                                               measureSelecter.getMeasureDuration()
-                                                       );
-                                               }
-                                       });
+                                       addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
                                }});
                                add(new JPanel() {{
                                        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
@@ -164,46 +158,34 @@ public class NewSequenceDialog extends JDialog {
                                        add(new JLabel("Transpose"));
                                        add(new JButton(" + Up ") {{
                                                setMargin(ZERO_INSETS);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               ChordProgression cp = createChordProgression();
-                                                               cp.transpose(1);
-                                                               setChordProgression(cp);
-                                                       }
+                                               addActionListener(e->{
+                                                       ChordProgression cp = createChordProgression();
+                                                       cp.transpose(1);
+                                                       setChordProgression(cp);
                                                });
                                        }});
                                        add(new JButton(" - Down ") {{
                                                setMargin(ZERO_INSETS);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               ChordProgression cp = createChordProgression();
-                                                               cp.transpose(-1);
-                                                               setChordProgression(cp);
-                                                       }
+                                               addActionListener(e->{
+                                                       ChordProgression cp = createChordProgression();
+                                                       cp.transpose(-1);
+                                                       setChordProgression(cp);
                                                });
                                        }});
                                        add(new JButton(" Enharmonic ") {{
                                                setMargin(ZERO_INSETS);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               ChordProgression cp = createChordProgression();
-                                                               cp.toggleEnharmonically();
-                                                               setChordProgression(cp);
-                                                       }
+                                               addActionListener(e->{
+                                                       ChordProgression cp = createChordProgression();
+                                                       cp.toggleEnharmonically();
+                                                       setChordProgression(cp);
                                                });
                                        }});
                                        add(new JButton("Relative key") {{
                                                setMargin(ZERO_INSETS);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               ChordProgression cp = createChordProgression();
-                                                               cp.toggleKeyMajorMinor();
-                                                               setChordProgression(cp);
-                                                       }
+                                               addActionListener(e->{
+                                                       ChordProgression cp = createChordProgression();
+                                                       cp.toggleKeyMajorMinor();
+                                                       setChordProgression(cp);
                                                });
                                        }});
                                }});
@@ -326,12 +308,7 @@ public class NewSequenceDialog extends JDialog {
                        trackSelecter.addActionListener(this);
                        chSelecter.comboBox.addActionListener(this);
                        keyboardPanel.keyboard.velocityModel.addChangeListener(
-                               new ChangeListener() {
-                                       public void stateChanged(ChangeEvent e) {
-                                               AbstractNoteTrackSpec ants = getTrackSpec();
-                                               ants.velocity = keyboardPanel.keyboard.velocityModel.getValue();
-                                       }
-                               }
+                               e -> getTrackSpec().velocity = keyboardPanel.keyboard.velocityModel.getValue()
                        );
                        pgSelecter.addActionListener(this);
                }
index a435e8e..88c5dea 100644 (file)
@@ -10,12 +10,12 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.charset.Charset;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MetaEventListener;
-import javax.sound.midi.MetaMessage;
 import javax.sound.midi.MidiSystem;
 import javax.sound.midi.Sequence;
 import javax.sound.midi.Sequencer;
@@ -63,7 +63,7 @@ public class PlaylistTableModel extends AbstractTableModel {
                }
        };
        /** 再生中のシーケンサーの秒位置リスナー */
-       private ChangeListener secondPosition = new ChangeListener() {
+       private ChangeListener mmssPosition = new ChangeListener() {
                private int value = 0;
                @Override
                public void stateChanged(ChangeEvent event) {
@@ -72,8 +72,7 @@ public class PlaylistTableModel extends AbstractTableModel {
                                int newValue = ((MidiSequencerModel)src).getValue() / 1000;
                                if(value == newValue) return;
                                value = newValue;
-                               int rowIndex = indexOfSequenceOnSequencer();
-                               fireTableCellUpdated(rowIndex, Column.POSITION.ordinal());
+                               fireTableCellUpdated(indexOfSequenceOnSequencer(), Column.POSITION.ordinal());
                        }
                }
                @Override
@@ -87,30 +86,10 @@ public class PlaylistTableModel extends AbstractTableModel {
         */
        public PlaylistTableModel(MidiSequencerModel sequencerModel) {
                this.sequencerModel = sequencerModel;
-               sequencerModel.addChangeListener(secondPosition);
-               sequencerModel.getSequencer().addMetaEventListener(new MetaEventListener() {
-                       /**
-                        * {@inheritDoc}
-                        *
-                        * <p>EOT (End Of Track、type==0x2F) を受信したとき、次の曲へ進みます。
-                        * </p>
-                        * <p>多くの場合、このメソッドは Swing の EDT(Event Dispatch Thread) ではなく
-                        * MIDI シーケンサの EDT から起動されるので、GUI 処理を Swing EDT に振り直します。
-                        * </p>
-                        */
-                       @Override
-                       public void meta(MetaMessage msg) {
-                               if( msg.getType() == 0x2F ) {
-                                       if( SwingUtilities.isEventDispatchThread() ) {
-                                               goNext();
-                                       } else {
-                                               SwingUtilities.invokeLater(new Runnable() {
-                                                       @Override
-                                                       public void run() { goNext(); }
-                                               });
-                                       }
-                               }
-                       }
+               sequencerModel.addChangeListener(mmssPosition);
+               // EOF(0x2F)が来たら曲の終わりなので次の曲へ進める
+               sequencerModel.getSequencer().addMetaEventListener(msg->{
+                       if(msg.getType() == 0x2F) SwingUtilities.invokeLater(()->goNext());
                });
                emptyTrackListTableModel = new SequenceTrackListTableModel(this, null, null);
                emptyEventListTableModel = new TrackEventListTableModel(emptyTrackListTableModel, null);
@@ -118,41 +97,35 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 次の曲へ進みます。
         *
-        * <p>リピートモードの場合は同じ曲をもう一度再生、
-        * そうでない場合は次の曲へ進んで再生します。
-        * 次の曲がなければ、そこで停止します。
-        * いずれの場合も曲の先頭へ戻ります。
+        * <p>リピートモードの場合は同じ曲をもう一度再生、そうでない場合は次の曲へ進んで再生します。
+        * 次の曲がなければ、そこで停止します。いずれの場合も曲の先頭へ戻ります。
         * </p>
         */
        private void goNext() {
                // とりあえず曲の先頭へ戻る
                sequencerModel.getSequencer().setMicrosecondPosition(0);
                if( (Boolean)toggleRepeatAction.getValue(Action.SELECTED_KEY) || loadNext(1) ) {
-                       // リピートモードのときはもう一度同じ曲を、
-                       // そうでない場合は次の曲を再生開始
+                       // リピートモードのときはもう一度同じ曲を、そうでない場合は次の曲を再生開始
                        sequencerModel.start();
                }
                else {
                        // 最後の曲が終わったので、停止状態にする
                        sequencerModel.stop();
-                       // ここでボタンが停止状態に変わったはずなので、
-                       // 通常であれば再生ボタンが自力で再描画するところだが、
-                       //
-                       // セルのレンダラーが描く再生ボタンには効かないようなので、
-                       // セルを突っついて再表示させる。
-                       int rowIndex = indexOfSequenceOnSequencer();
-                       int colIndex = Column.PLAY.ordinal();
-                       fireTableCellUpdated(rowIndex, colIndex);
+                       // ここでボタンが停止状態に変わったはずなので、通常であれば再生ボタンが自力で再描画するところだが、
+                       // セルのレンダラーが描く再生ボタンには効かないようなので、セルを突っついて再表示させる。
+                       fireTableCellUpdated(indexOfSequenceOnSequencer(), Column.PLAY.ordinal());
                }
        }
        /**
         * シーケンスリスト
         */
-       private List<SequenceTrackListTableModel> sequenceList = new Vector<>();
+       private List<SequenceTrackListTableModel> sequenceModelList = new Vector<>();
        /**
         * このプレイリストが保持している {@link SequenceTrackListTableModel} のリストを返します。
         */
-       public List<SequenceTrackListTableModel> getSequenceList() { return sequenceList; }
+       public List<SequenceTrackListTableModel> getSequenceModelList() {
+               return sequenceModelList;
+       }
        /**
         * 行が選択されているときだけイネーブルになるアクション
         */
@@ -181,7 +154,8 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 繰り返し再生ON/OFF切り替えアクション
         */
-       public Action toggleRepeatAction = new AbstractAction() {
+       public Action getToggleRepeatAction() { return toggleRepeatAction; }
+       private Action toggleRepeatAction = new AbstractAction() {
                {
                        putValue(SHORT_DESCRIPTION, "Repeat - 繰り返し再生");
                        putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.REPEAT_ICON));
@@ -193,7 +167,8 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 曲の先頭または前の曲へ戻るアクション
         */
-       public Action moveToTopAction = new AbstractAction() {
+       public Action getMoveToTopAction() { return moveToTopAction; }
+       private Action moveToTopAction = new AbstractAction() {
                {
                        putValue(SHORT_DESCRIPTION,
                                "Move to top or previous song - 曲の先頭または前の曲へ戻る"
@@ -208,7 +183,8 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 次の曲へ進むアクション
         */
-       public Action moveToBottomAction = new AbstractAction() {
+       public Action getMoveToBottomAction() { return moveToBottomAction; }
+       private Action moveToBottomAction = new AbstractAction() {
                {
                        putValue(SHORT_DESCRIPTION, "Move to next song - 次の曲へ進む");
                        putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BOTTOM_ICON));
@@ -217,7 +193,6 @@ public class PlaylistTableModel extends AbstractTableModel {
                        if(loadNext(1)) sequencerModel.setValue(0);
                }
        };
-
        /**
         * 列の列挙型
         */
@@ -235,7 +210,7 @@ public class PlaylistTableModel extends AbstractTableModel {
                        public boolean isCellEditable() { return true; } // ダブルクリックだけ有効
                        @Override
                        public Object getValueOf(SequenceTrackListTableModel sequenceModel) {
-                               return sequenceModel.isOnSequencer() ? sequenceModel.getParent().secondPosition : "";
+                               return sequenceModel.isOnSequencer() ? sequenceModel.getParent().mmssPosition : "";
                        }
                },
                /** シーケンスの時間長(分:秒) */
@@ -301,13 +276,21 @@ public class PlaylistTableModel extends AbstractTableModel {
                DIVISION_TYPE("DivType", String.class, 50) {
                        @Override
                        public Object getValueOf(SequenceTrackListTableModel sequenceModel) {
-                               float divType = sequenceModel.getSequence().getDivisionType();
-                               if( divType == Sequence.PPQ ) return "PPQ";
-                               else if( divType == Sequence.SMPTE_24 ) return "SMPTE_24";
-                               else if( divType == Sequence.SMPTE_25 ) return "SMPTE_25";
-                               else if( divType == Sequence.SMPTE_30 ) return "SMPTE_30";
-                               else if( divType == Sequence.SMPTE_30DROP ) return "SMPTE_30DROP";
-                               else return "[Unknown]";
+                               float dt = sequenceModel.getSequence().getDivisionType();
+                               String dtLabel = divisionTypeLabels.get(dt);
+                               return dtLabel == null ? "[Unknown]" : dtLabel;
+                       }
+               };
+               /**
+                * タイミング分割形式に対応するラベル文字列
+                */
+               private static final Map<Float,String> divisionTypeLabels = new HashMap<Float,String>() {
+                       {
+                               put(Sequence.PPQ, "PPQ");
+                               put(Sequence.SMPTE_24, "SMPTE_24");
+                               put(Sequence.SMPTE_25, "SMPTE_25");
+                               put(Sequence.SMPTE_30, "SMPTE_30");
+                               put(Sequence.SMPTE_30DROP, "SMPTE_30DROP");
                        }
                };
                String title;
@@ -329,7 +312,7 @@ public class PlaylistTableModel extends AbstractTableModel {
        }
 
        @Override
-       public int getRowCount() { return sequenceList.size(); }
+       public int getRowCount() { return sequenceModelList.size(); }
        @Override
        public int getColumnCount() { return Column.values().length; }
        @Override
@@ -343,25 +326,25 @@ public class PlaylistTableModel extends AbstractTableModel {
        @Override
        public Object getValueAt(int row, int column) {
                PlaylistTableModel.Column c = Column.values()[column];
-               return c == Column.NUMBER ? row : c.getValueOf(sequenceList.get(row));
+               return c == Column.NUMBER ? row : c.getValueOf(sequenceModelList.get(row));
        }
        @Override
        public void setValueAt(Object val, int row, int column) {
                switch(Column.values()[column]) {
                case FILENAME:
                        // ファイル名の変更
-                       sequenceList.get(row).setFilename((String)val);
+                       sequenceModelList.get(row).setFilename((String)val);
                        fireTableCellUpdated(row, column);
                        break;
                case NAME:
                        // シーケンス名の設定または変更
-                       if( sequenceList.get(row).setName((String)val) )
+                       if( sequenceModelList.get(row).setName((String)val) )
                                fireTableCellUpdated(row, Column.MODIFIED.ordinal());
                        fireTableCellUpdated(row, column);
                        break;
                case CHARSET:
                        // 文字コードの変更
-                       SequenceTrackListTableModel seq = sequenceList.get(row);
+                       SequenceTrackListTableModel seq = sequenceModelList.get(row);
                        seq.charset = Charset.forName(val.toString());
                        fireTableCellUpdated(row, column);
                        // シーケンス名の表示更新
@@ -376,47 +359,24 @@ public class PlaylistTableModel extends AbstractTableModel {
         * このプレイリストに読み込まれた全シーケンスの合計時間長を返します。
         * @return 全シーケンスの合計時間長 [秒]
         */
-       public int getTotalSeconds() {
+       public int getTotalTimeInSeconds() {
                int total = 0;
                long usec;
-               for( SequenceTrackListTableModel m : sequenceList ) {
+               for( SequenceTrackListTableModel m : sequenceModelList ) {
                        usec = m.getSequence().getMicrosecondLength();
                        total += (int)( (usec < 0 ? usec += 0x100000000L : usec)/1000L/1000L );
                }
                return total;
        }
        /**
-        * 未保存の修正内容を持つシーケンスがあるか調べます。
-        * @return 未保存の修正内容を持つシーケンスがあればtrue
-        */
-       public boolean isModified() {
-               for( SequenceTrackListTableModel m : sequenceList ) if( m.isModified() ) return true;
-               return false;
-       }
-       /**
-        * 選択したシーケンスに未保存の修正内容があることを記録します。
-        * @param selModel 選択状態
-        * @param isModified 未保存の修正内容があるときtrue
-        */
-       public void setModified(boolean isModified) {
-               int minIndex = sequenceListSelectionModel.getMinSelectionIndex();
-               int maxIndex = sequenceListSelectionModel.getMaxSelectionIndex();
-               for( int i = minIndex; i <= maxIndex; i++ ) {
-                       if( sequenceListSelectionModel.isSelectedIndex(i) ) {
-                               sequenceList.get(i).setModified(isModified);
-                               fireTableCellUpdated(i, Column.MODIFIED.ordinal());
-                       }
-               }
-       }
-       /**
         * 選択されたMIDIシーケンスのテーブルモデルを返します。
         * @return 選択されたMIDIシーケンスのテーブルモデル(非選択時はnull)
         */
        public SequenceTrackListTableModel getSelectedSequenceModel() {
                if( sequenceListSelectionModel.isSelectionEmpty() ) return null;
                int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex();
-               if( selectedIndex >= sequenceList.size() ) return null;
-               return sequenceList.get(selectedIndex);
+               if( selectedIndex >= sequenceModelList.size() ) return null;
+               return sequenceModelList.get(selectedIndex);
        }
        /**
         * 指定されたシーケンスの更新済みフラグを変更して全ての列を再表示します。
@@ -424,7 +384,7 @@ public class PlaylistTableModel extends AbstractTableModel {
         * @param isModified 更新済みフラグ
         */
        public void fireSequenceModified(SequenceTrackListTableModel sequenceTableModel, boolean isModified) {
-               int index = sequenceList.indexOf(sequenceTableModel);
+               int index = sequenceModelList.indexOf(sequenceTableModel);
                if( index < 0 ) return;
                sequenceTableModel.setModified(isModified);
                fireTableRowsUpdated(index, index);
@@ -438,69 +398,64 @@ public class PlaylistTableModel extends AbstractTableModel {
                int minIndex = sequenceListSelectionModel.getMinSelectionIndex();
                int maxIndex = sequenceListSelectionModel.getMaxSelectionIndex();
                for( int index = minIndex; index <= maxIndex; index++ ) {
-                       sequenceList.get(index).setModified(isModified);
+                       sequenceModelList.get(index).setModified(isModified);
                }
                fireTableRowsUpdated(minIndex, maxIndex);
        }
        /**
-        * ファイル名つきのMIDIシーケンスを追加します。
-        * @param sequence MIDIシーケンス
-        * @param filename ファイル名
+        * MIDIシーケンスを追加します。
+        * @param sequence MIDIシーケンス(nullの場合、シーケンスを自動生成して追加)
+        * @param filename ファイル名(nullの場合、ファイル名なし)
         * @return 追加されたシーケンスのインデックス(先頭が 0)
         */
        public int addSequence(Sequence sequence, String filename) {
-               sequenceList.add( new SequenceTrackListTableModel(this, sequence, filename) );
-               int lastIndex = sequenceList.size() - 1;
+               if( sequence == null ) sequence = (new ChordProgression()).toMidiSequence();
+               sequenceModelList.add(new SequenceTrackListTableModel(this, sequence, filename));
+               //
+               // 末尾に行が追加されたので、再描画してもらう
+               int lastIndex = sequenceModelList.size() - 1;
                fireTableRowsInserted(lastIndex, lastIndex);
+               sequenceListSelectionModel.setSelectionInterval(lastIndex, lastIndex);
                return lastIndex;
        }
        /**
-        * デフォルトの内容でMIDIシーケンスを作成して追加します。
-        * @return 追加されたMIDIシーケンスのインデックス(先頭が 0)
-        */
-       public int addSequence() {
-               Sequence seq = (new ChordProgression()).toMidiSequence();
-               return seq == null ? -1 : addSequence(seq,null);
-       }
-       /**
         * バイト列とファイル名からMIDIシーケンスを追加します。
-        * バイト列が null の場合、空のMIDIシーケンスを追加します。
-        * @param data バイト列
+        * @param data バイト列(nullの場合、シーケンスを自動生成して追加)
         * @param filename ファイル名
         * @return 追加先インデックス(先頭が 0)
-        * @throws IOException ã\83\95ã\82¡ã\82¤ã\83«読み込みに失敗した場合
+        * @throws IOException ã\83\90ã\82¤ã\83\88å\88\97ã\81®読み込みに失敗した場合
         * @throws InvalidMidiDataException MIDIデータが正しくない場合
         */
        public int addSequence(byte[] data, String filename) throws IOException, InvalidMidiDataException {
-               if( data == null ) return addSequence();
-               int lastIndex;
-               try (InputStream in = new ByteArrayInputStream(data)) {
-                       lastIndex = addSequence(MidiSystem.getSequence(in), filename);
-               } catch( IOException|InvalidMidiDataException e ) {
-                       throw e;
+               Sequence sequence = null;
+               if( data != null ) {
+                       try (InputStream in = new ByteArrayInputStream(data)) {
+                               sequence = MidiSystem.getSequence(in);
+                       } catch( IOException|InvalidMidiDataException e ) {
+                               throw e;
+                       }
                }
-               sequenceListSelectionModel.setSelectionInterval(lastIndex, lastIndex);
-               return lastIndex;
+               return addSequence(sequence, filename);
        }
        /**
         * MIDIファイルを追加します。
-        * ファイルが null の場合、デフォルトのMIDIシーケンスを追加します。
-        * @param midiFile MIDIファイル
+        * @param midiFile MIDIファイル(nullの場合、シーケンスを自動生成して追加)
         * @return 追加先インデックス(先頭が 0)
-        * @throws InvalidMidiDataException ファイル内のMIDIデータが正しくない場合
         * @throws IOException ファイル入出力に失敗した場合
+        * @throws InvalidMidiDataException ファイル内のMIDIデータが正しくない場合
         */
        public int addSequence(File midiFile) throws InvalidMidiDataException, IOException {
-               if( midiFile == null ) return addSequence();
-               int lastIndex;
-               try (FileInputStream in = new FileInputStream(midiFile)) {
-                       Sequence seq = MidiSystem.getSequence(in);
-                       String filename = midiFile.getName();
-                       lastIndex = addSequence(seq, filename);
-               } catch( InvalidMidiDataException|IOException e ) {
-                       throw e;
+               Sequence sequence = null;
+               String filename = null;
+               if( midiFile != null ) {
+                       try (FileInputStream in = new FileInputStream(midiFile)) {
+                               sequence = MidiSystem.getSequence(in);
+                       } catch( IOException|InvalidMidiDataException e ) {
+                               throw e;
+                       }
+                       filename = midiFile.getName();
                }
-               return lastIndex;
+               return addSequence(sequence, filename);
        }
        /**
         * MIDIシーケンスを追加し、再生されていなかった場合は追加したシーケンスから再生を開始します。
@@ -555,7 +510,7 @@ public class PlaylistTableModel extends AbstractTableModel {
        public void removeSelectedSequence() throws InvalidMidiDataException {
                if( sequenceListSelectionModel.isSelectionEmpty() ) return;
                int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex();
-               SequenceTrackListTableModel removedSequence = sequenceList.remove(selectedIndex);
+               SequenceTrackListTableModel removedSequence = sequenceModelList.remove(selectedIndex);
                if( removedSequence.isOnSequencer() ) sequencerModel.setSequenceTrackListTableModel(null);
                fireTableRowsDeleted(selectedIndex, selectedIndex);
        }
@@ -569,7 +524,7 @@ public class PlaylistTableModel extends AbstractTableModel {
         */
        public void loadToSequencer(int newRowIndex) throws InvalidMidiDataException {
                SequenceTrackListTableModel oldSeq = sequencerModel.getSequenceTrackListTableModel();
-               SequenceTrackListTableModel newSeq = (newRowIndex < 0 ? null : sequenceList.get(newRowIndex));
+               SequenceTrackListTableModel newSeq = (newRowIndex < 0 ? null : sequenceModelList.get(newRowIndex));
                if( oldSeq == newSeq ) return;
                sequencerModel.setSequenceTrackListTableModel(newSeq);
                int columnIndices[] = {
@@ -577,7 +532,7 @@ public class PlaylistTableModel extends AbstractTableModel {
                        Column.POSITION.ordinal(),
                };
                if( oldSeq != null ) {
-                       int oldRowIndex = sequenceList.indexOf(oldSeq);
+                       int oldRowIndex = sequenceModelList.indexOf(oldSeq);
                        for( int columnIndex : columnIndices ) fireTableCellUpdated(oldRowIndex, columnIndex);
                }
                if( newSeq != null ) {
@@ -590,25 +545,21 @@ public class PlaylistTableModel extends AbstractTableModel {
         * @return 現在シーケンサにロードされているシーケンスのインデックス
         */
        public int indexOfSequenceOnSequencer() {
-               return sequenceList.indexOf(sequencerModel.getSequenceTrackListTableModel());
+               return sequenceModelList.indexOf(sequencerModel.getSequenceTrackListTableModel());
        }
        /**
         * 引数で示された数だけ次へ進めたシーケンスをロードします。
         * @param offset 進みたいシーケンス数
         * @return true:ロード成功、false:これ以上進めない
-        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
        public boolean loadNext(int offset) {
                int loadedIndex = indexOfSequenceOnSequencer();
                int index = (loadedIndex < 0 ? 0 : loadedIndex + offset);
-               if( index < 0 || index >= sequenceList.size() ) return false;
+               if( index < 0 || index >= sequenceModelList.size() ) return false;
                try {
                        loadToSequencer(index);
                } catch (InvalidMidiDataException ex) {
-                       ex.printStackTrace();
-                       JOptionPane.showMessageDialog(
-                               null, ex.getMessage(),
-                               ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
+                       JOptionPane.showMessageDialog(null, ex, ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
                        return false;
                }
                return true;
index 3d48fdd..7d905cb 100644 (file)
@@ -1,8 +1,6 @@
 package camidion.chordhelper.midieditor;
 
 import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -91,19 +89,16 @@ public class SequencerSpeedSlider extends JPanel {
                                        {
                                                setSize(new Dimension(20,20));
                                                setMargin(ChordHelperApplet.ZERO_INSETS);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               int max = maxFactors.size() - 1;
-                                                               if( index >= max ) return;
-                                                               changeSliderScale(maxFactors.get(++index));
-                                                               if( index >= max ) {
-                                                                       setEnabled(false);
-                                                                       push.requestFocusInWindow();
-                                                                       return;
-                                                               }
-                                                               push.setEnabled(true);
+                                               addActionListener(e->{
+                                                       int max = maxFactors.size() - 1;
+                                                       if( index >= max ) return;
+                                                       changeSliderScale(maxFactors.get(++index));
+                                                       if( index >= max ) {
+                                                               setEnabled(false);
+                                                               push.requestFocusInWindow();
+                                                               return;
                                                        }
+                                                       push.setEnabled(true);
                                                });
                                        }
                                });
@@ -112,18 +107,15 @@ public class SequencerSpeedSlider extends JPanel {
                                                setSize(new Dimension(20,20));
                                                setMargin(ChordHelperApplet.ZERO_INSETS);
                                                setEnabled(false);
-                                               addActionListener(new ActionListener() {
-                                                       @Override
-                                                       public void actionPerformed(ActionEvent e) {
-                                                               if( index <= 0 ) return;
-                                                               changeSliderScale(maxFactors.get(--index));
-                                                               if( index <= 0 ) {
-                                                                       setEnabled(false);
-                                                                       pull.requestFocusInWindow();
-                                                                       return;
-                                                               }
-                                                               pull.setEnabled(true);
+                                               addActionListener(e->{
+                                                       if( index <= 0 ) return;
+                                                       changeSliderScale(maxFactors.get(--index));
+                                                       if( index <= 0 ) {
+                                                               setEnabled(false);
+                                                               pull.requestFocusInWindow();
+                                                               return;
                                                        }
+                                                       pull.setEnabled(true);
                                                });
                                        }
                                });
index 893e05c..5866895 100644 (file)
@@ -464,9 +464,7 @@ public class ChordProgression {
         * コード進行をもとに MIDI シーケンスを生成します。
         * @return MIDIシーケンス
         */
-       public Sequence toMidiSequence() {
-               return toMidiSequence(48);
-       }
+       public Sequence toMidiSequence() { return toMidiSequence(48); }
        /**
         * 指定のタイミング解像度で、
         * コード進行をもとに MIDI シーケンスを生成します。
@@ -489,20 +487,16 @@ public class ChordProgression {
         */
        public Sequence toMidiSequence(
                int ppq, int startMeasure, int endMeasure,
-               FirstTrackSpec firstTrack,
-               Vector<AbstractNoteTrackSpec> trackSpecs
+               FirstTrackSpec firstTrack, Vector<AbstractNoteTrackSpec> trackSpecs
        ) {
                Sequence seq;
                try {
                        seq = new Sequence(Sequence.PPQ, ppq);
-               } catch ( InvalidMidiDataException e ) {
-                       e.printStackTrace();
-                       return null;
+               } catch( InvalidMidiDataException imde ) {
+                       throw new IllegalArgumentException("Unexpected error", imde);
                }
                // マスタートラックの生成
-               if( firstTrack == null ) {
-                       firstTrack = new FirstTrackSpec();
-               }
+               if( firstTrack == null ) firstTrack = new FirstTrackSpec();
                firstTrack.key = this.key;
                firstTrack.createTrack( seq, startMeasure, endMeasure );
                //