From 47f03942783a993ffca754cba0fb876aac3154e0 Mon Sep 17 00:00:00 2001 From: Akiyoshi Kamide Date: Sun, 15 May 2016 01:09:59 +0900 Subject: [PATCH] =?utf8?q?=E3=83=BB=E3=83=80=E3=82=A4=E3=82=A2=E3=83=AD?= =?utf8?q?=E3=82=B0=E3=81=8B=E3=82=89=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?utf8?q?=E3=82=92=E9=96=8B=E3=81=84=E3=81=9F=E3=81=A8=E3=81=8D=E3=82=82?= =?utf8?q?=E8=87=AA=E5=8B=95=E5=86=8D=E7=94=9F=E3=81=99=E3=82=8B=E3=82=88?= =?utf8?q?=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=20=E3=83=BB=E3=83=AA?= =?utf8?q?=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/camidion/chordhelper/ChordHelperApplet.java | 53 +--- .../mididevice/AbstractVirtualMidiDevice.java | 24 +- .../chordhelper/mididevice/MidiSequencerModel.java | 10 +- .../chordhelper/midieditor/MidiSequenceEditor.java | 351 +++++++-------------- .../chordhelper/midieditor/PlaylistTableModel.java | 54 ++-- 5 files changed, 165 insertions(+), 327 deletions(-) diff --git a/src/camidion/chordhelper/ChordHelperApplet.java b/src/camidion/chordhelper/ChordHelperApplet.java index e124716..0828ad6 100644 --- a/src/camidion/chordhelper/ChordHelperApplet.java +++ b/src/camidion/chordhelper/ChordHelperApplet.java @@ -22,12 +22,10 @@ import java.net.URISyntaxException; import java.net.URL; import java.security.AccessControlException; import java.util.Arrays; -import java.util.Vector; 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.Box; import javax.swing.BoxLayout; @@ -59,10 +57,10 @@ import camidion.chordhelper.mididevice.MidiDeviceDialog; import camidion.chordhelper.mididevice.MidiTransceiverListModelList; import camidion.chordhelper.mididevice.SequencerMeasureView; import camidion.chordhelper.mididevice.SequencerTimeView; -import camidion.chordhelper.mididevice.VirtualMidiDevice; import camidion.chordhelper.midieditor.Base64Dialog; import camidion.chordhelper.midieditor.KeySignatureLabel; import camidion.chordhelper.midieditor.MidiSequenceEditor; +import camidion.chordhelper.midieditor.NewSequenceDialog; import camidion.chordhelper.midieditor.SequenceTickIndex; import camidion.chordhelper.midieditor.SequenceTrackListTableModel; import camidion.chordhelper.midieditor.TempoSelecter; @@ -100,9 +98,10 @@ public class ChordHelperApplet extends JApplet { * @return 追加先のインデックス値(0から始まる)。追加できなかったときは -1 */ public int addRandomSongToPlaylist(int measureLength) { - deviceModelList.getEditorDialog().newSequenceDialog.setRandomChordProgression(measureLength); - Sequence sequence = deviceModelList.getEditorDialog().newSequenceDialog.getMidiSequence(); - return deviceModelList.getEditorDialog().sequenceListTable.getModel().addSequenceAndPlay(sequence); + MidiSequenceEditor editor = deviceModelList.getEditorDialog(); + NewSequenceDialog d = editor.newSequenceDialog; + d.setRandomChordProgression(measureLength); + return editor.sequenceListTable.getModel().addSequenceAndPlay(d.getMidiSequence()); } /** * URLで指定されたMIDIファイルをプレイリストへ追加します。 @@ -288,7 +287,7 @@ public class ChordHelperApplet extends JApplet { */ public static class VersionInfo { public static final String NAME = "MIDI Chord Helper"; - public static final String VERSION = "Ver.20160511.1"; + public static final String VERSION = "Ver.20160514.1"; public static final String COPYRIGHT = "Copyright (C) 2004-2016"; public static final String AUTHER = "@きよし - Akiyoshi Kamide"; public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/"; @@ -353,8 +352,7 @@ public class ChordHelperApplet extends JApplet { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog( - null, this, "Version info", - JOptionPane.INFORMATION_MESSAGE, imageIcon + null, this, "Version info", JOptionPane.INFORMATION_MESSAGE, imageIcon ); } } @@ -445,9 +443,7 @@ public class ChordHelperApplet extends JApplet { keyboardCenterPanel.keyboard.addPianoKeyboardListener( new PianoKeyboardAdapter() { @Override - public void pianoKeyPressed(int n, InputEvent e) { - chordDiagram.clear(); - } + public void pianoKeyPressed(int n, InputEvent e) { chordDiagram.clear(); } } ); keySelecter.keysigCombobox.addActionListener( @@ -463,11 +459,7 @@ public class ChordHelperApplet extends JApplet { keyboardCenterPanel.keyboard.setPreferredSize(new Dimension(571, 80)); }}; deviceModelList = new MidiTransceiverListModelList( - new Vector() { - { - add(keyboardPanel.keyboardCenterPanel.keyboard.midiDevice); - } - } + Arrays.asList(keyboardPanel.keyboardCenterPanel.keyboard.midiDevice) ); deviceModelList.getEditorDialog().setIconImage(iconImage); new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, deviceModelList.getEditorDialog().dropTargetListener, true); @@ -496,18 +488,14 @@ public class ChordHelperApplet extends JApplet { }}; keysigLabel = new KeySignatureLabel() {{ addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e) { - chordMatrix.setKeySignature(getKey()); - } + public void mousePressed(MouseEvent e) { chordMatrix.setKeySignature(getKey()); } }); }}; deviceModelList.getSequencerModel().getSequencer().addMetaEventListener( new MetaEventListener() { class SetKeySignatureRunnable implements Runnable { Key key; - public SetKeySignatureRunnable(Key key) { - this.key = key; - } + public SetKeySignatureRunnable(Key key) { this.key = key; } @Override public void run() { setKeySignature(key); } } @@ -517,9 +505,7 @@ public class ChordHelperApplet extends JApplet { case 0x59: // Key signature (2 bytes) : 調号 Key key = new Key(msg.getData()); if( ! SwingUtilities.isEventDispatchThread() ) { - SwingUtilities.invokeLater( - new SetKeySignatureRunnable(key) - ); + SwingUtilities.invokeLater(new SetKeySignatureRunnable(key)); } setKeySignature(key); break; @@ -714,22 +700,15 @@ public class ChordHelperApplet extends JApplet { add(anoGakkiPane = new AnoGakkiPane(), JLayeredPane.PALETTE_LAYER); addComponentListener(new ComponentAdapter() { @Override - public void componentResized(ComponentEvent e) { - adjustSize(); - } + public void componentResized(ComponentEvent e) { adjustSize(); } @Override - public void componentShown(ComponentEvent e) { - adjustSize(); - } - private void adjustSize() { - anoGakkiPane.setBounds(getBounds()); - } + public void componentShown(ComponentEvent e) { adjustSize(); } + private void adjustSize() { anoGakkiPane.setBounds(getBounds()); } }); setLayout(new BorderLayout()); setOpaque(true); add(mainSplitPane = new JSplitPane( - JSplitPane.VERTICAL_SPLIT, - chordMatrix, keyboardSequencerPanel + JSplitPane.VERTICAL_SPLIT, chordMatrix, keyboardSequencerPanel ){ { setResizeWeight(0.5); diff --git a/src/camidion/chordhelper/mididevice/AbstractVirtualMidiDevice.java b/src/camidion/chordhelper/mididevice/AbstractVirtualMidiDevice.java index 5116c55..d379353 100644 --- a/src/camidion/chordhelper/mididevice/AbstractVirtualMidiDevice.java +++ b/src/camidion/chordhelper/mididevice/AbstractVirtualMidiDevice.java @@ -58,15 +58,11 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice { * MIDI IN 接続の最大数を設定します。デフォルト値は -1 です。 * @param maxReceivers MIDI IN 接続の最大数、または利用可能な接続数に制限がない場合は -1。 */ - protected void setMaxReceivers(int maxReceivers) { - this.maxReceivers = maxReceivers; - } + protected void setMaxReceivers(int maxReceivers) { this.maxReceivers = maxReceivers; } @Override public int getMaxReceivers() { return maxReceivers; } @Override - public Receiver getReceiver() { - return rxList.isEmpty() ? null : rxList.get(0); - } + public Receiver getReceiver() { return rxList.isEmpty() ? null : rxList.get(0); } protected void setReceiver(Receiver rx) { if( maxReceivers == 0 ) return; if( ! rxList.isEmpty() ) rxList.clear(); @@ -86,14 +82,10 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice { * MIDI OUT 接続の最大数を設定します。デフォルト値は -1 です。 * @param maxTransmitters MIDI OUT 接続の最大数、または利用可能な接続数に制限がない場合は -1。 */ - protected void setMaxTransmitters(int maxTransmitters) { - this.maxTransmitters = maxTransmitters; - } + protected void setMaxTransmitters(int maxTransmitters) { this.maxTransmitters = maxTransmitters; } @Override public Transmitter getTransmitter() throws MidiUnavailableException { - if( maxTransmitters == 0 ) { - throw new MidiUnavailableException(); - } + if( maxTransmitters == 0 ) throw new MidiUnavailableException(); Transmitter new_tx = new Transmitter() { private Receiver rx = null; @Override @@ -128,9 +120,7 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice { * @param vmd 仮想MIDIデバイス * @param channel MIDIチャンネルインデックス(チャンネル 1 のとき 0) */ - public VirtualDeviceMidiChannel(int channel) { - this.channel = channel; - } + public VirtualDeviceMidiChannel(int channel) { this.channel = channel; } private void sendShortMessage(int command, int data1, int data2) { try { sendMidiMessage(new ShortMessage(command, channel, data1, data2)); @@ -139,9 +129,7 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice { } } @Override - public void noteOff(int noteNumber) { - noteOff(noteNumber, 64); - } + public void noteOff(int noteNumber) { noteOff(noteNumber, 64); } @Override public void noteOff(int noteNumber, int velocity) { sendShortMessage(ShortMessage.NOTE_OFF, noteNumber, velocity); diff --git a/src/camidion/chordhelper/mididevice/MidiSequencerModel.java b/src/camidion/chordhelper/mididevice/MidiSequencerModel.java index e346a09..4c70cda 100644 --- a/src/camidion/chordhelper/mididevice/MidiSequencerModel.java +++ b/src/camidion/chordhelper/mididevice/MidiSequencerModel.java @@ -252,8 +252,8 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun return sequenceTableModel; } /** - * MIDIトラックリストテーブルモデルを - * このシーケンサーモデルにセットします。 + * MIDIトラックリストテーブルモデルをこのシーケンサーモデルにセットします。 + * nullを指定してアンセットすることもできます。 * @param sequenceTableModel MIDIトラックリストテーブルモデル * @return 成功したらtrue */ @@ -266,8 +266,7 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun // if( sequenceTableModel != null || getSequencer().isOpen() ) { Sequence sequence = null; - if( sequenceTableModel != null ) - sequence = sequenceTableModel.getSequence(); + if( sequenceTableModel != null ) sequence = sequenceTableModel.getSequence(); try { getSequencer().setSequence(sequence); } catch ( InvalidMidiDataException e ) { @@ -291,8 +290,7 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun * @param measureOffset 何小節進めるか(戻したいときは負数を指定) */ private void moveMeasure(int measureOffset) { - if( measureOffset == 0 || sequenceTableModel == null ) - return; + if( measureOffset == 0 || sequenceTableModel == null ) return; SequenceTickIndex seqIndex = sequenceTableModel.getSequenceTickIndex(); Sequencer sequencer = getSequencer(); int measurePosition = seqIndex.tickToMeasure(sequencer.getTickPosition()); diff --git a/src/camidion/chordhelper/midieditor/MidiSequenceEditor.java b/src/camidion/chordhelper/midieditor/MidiSequenceEditor.java index 6a21231..0b5e75d 100644 --- a/src/camidion/chordhelper/midieditor/MidiSequenceEditor.java +++ b/src/camidion/chordhelper/midieditor/MidiSequenceEditor.java @@ -25,6 +25,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.security.AccessControlException; +import java.util.Arrays; import java.util.EventObject; import java.util.List; import java.util.Map; @@ -59,7 +60,6 @@ import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; -import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellEditor; @@ -83,6 +83,24 @@ import camidion.chordhelper.music.MIDISpec; * http://www.yk.rim.or.jp/~kamide/music/chordhelper/ */ public class MidiSequenceEditor extends JDialog { + /** + * このダイアログを表示するアクション + */ + public Action openAction = new AbstractAction("Edit/Playlist/Speed", new ButtonIcon(ButtonIcon.EDIT_ICON)) { + { + String tooltip = "MIDIシーケンスの編集/プレイリスト/再生速度調整"; + putValue(Action.SHORT_DESCRIPTION, tooltip); + } + @Override + public void actionPerformed(ActionEvent e) { + if( isVisible() ) toFront(); else setVisible(true); + } + }; + + /** + * このMIDIエディタにおける操作音の出力先となる仮想MIDIデバイスを返します。 + */ + public VirtualMidiDevice getVirtualMidiDevice() { return virtualMidiDevice; } private static VirtualMidiDevice virtualMidiDevice = new AbstractVirtualMidiDevice() { { info = new MyInfo(); @@ -93,61 +111,24 @@ public class MidiSequenceEditor extends JDialog { */ protected MyInfo info; @Override - public Info getDeviceInfo() { - return info; - } + public Info getDeviceInfo() { return info; } class MyInfo extends Info { - protected MyInfo() { - super("MIDI Editor","Unknown vendor","MIDI sequence editor",""); - } + protected MyInfo() { super("MIDI Editor","Unknown vendor","MIDI sequence editor",""); } } }; - /** - * このMIDIエディタの仮想MIDIデバイスを返します。 - */ - public VirtualMidiDevice getVirtualMidiDevice() { - return virtualMidiDevice; - } - /** - * このダイアログを表示するアクション - */ - public Action openAction = new AbstractAction( - "Edit/Playlist/Speed", new ButtonIcon(ButtonIcon.EDIT_ICON) - ) { - { - String tooltip = "MIDIシーケンスの編集/プレイリスト/再生速度調整"; - putValue(Action.SHORT_DESCRIPTION, tooltip); - } - @Override - public void actionPerformed(ActionEvent e) { open(); } - }; - /** - * このダイアログを開きます。すでに開かれていた場合は前面に移動します。 - */ - public void open() { - if( isVisible() ) toFront(); else setVisible(true); - } + /** * エラーメッセージダイアログを表示します。 * @param message エラーメッセージ */ - public void showError(String message) { - JOptionPane.showMessageDialog( - this, message, - ChordHelperApplet.VersionInfo.NAME, - JOptionPane.ERROR_MESSAGE - ); - } + public void showError(String message) { showMessage(message, JOptionPane.ERROR_MESSAGE); } /** * 警告メッセージダイアログを表示します。 * @param message 警告メッセージ */ - public void showWarning(String message) { - JOptionPane.showMessageDialog( - this, message, - ChordHelperApplet.VersionInfo.NAME, - JOptionPane.WARNING_MESSAGE - ); + public void showWarning(String message) { showMessage(message, JOptionPane.WARNING_MESSAGE); } + private void showMessage(String message, int messageType) { + JOptionPane.showMessageDialog(this, message, ChordHelperApplet.VersionInfo.NAME, messageType); } /** * 確認ダイアログを表示します。 @@ -155,13 +136,10 @@ public class MidiSequenceEditor extends JDialog { * @return 確認OKのときtrue */ boolean confirm(String message) { - return JOptionPane.showConfirmDialog( - this, message, - ChordHelperApplet.VersionInfo.NAME, - JOptionPane.YES_NO_OPTION, - JOptionPane.WARNING_MESSAGE - ) == JOptionPane.YES_OPTION ; + return JOptionPane.showConfirmDialog(this, message, ChordHelperApplet.VersionInfo.NAME, + JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION ; } + /** * ドロップされた複数のMIDIファイルを読み込むリスナー */ @@ -193,31 +171,45 @@ public class MidiSequenceEditor extends JDialog { event.dropComplete(false); } }; + /** * 複数のMIDIファイルを読み込み、再生されていなかったら再生します。 * すでに再生されていた場合、このエディタダイアログを表示します。 * * @param fileList 読み込むMIDIファイルのリスト + * @see #loadAndPlay(File) */ public void loadAndPlay(List fileList) { - int firstIndex = -1; + int indexOfAddedTop = -1; PlaylistTableModel playlist = sequenceListTable.getModel(); try { - firstIndex = playlist.addSequences(fileList); + indexOfAddedTop = playlist.addSequences(fileList); } catch(IOException|InvalidMidiDataException e) { showWarning(e.getMessage()); } catch(AccessControlException e) { showError(e.getMessage()); e.printStackTrace(); } - if(playlist.sequencerModel.getSequencer().isRunning()) { - open(); + MidiSequencerModel sequencerModel = playlist.sequencerModel; + if( sequencerModel.getSequencer().isRunning() ) { + String command = (String)openAction.getValue(Action.NAME); + openAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command)); + return; } - else if( firstIndex >= 0 ) { - playlist.loadToSequencer(firstIndex); - playlist.sequencerModel.start(); + if( indexOfAddedTop >= 0 ) { + playlist.loadToSequencer(indexOfAddedTop); + sequencerModel.start(); } } + /** + * 1件のMIDIファイルを読み込み、再生されていなかったら再生します。 + * すでに再生されていた場合、このエディタダイアログを表示します。 + * + * @param file 読み込むMIDIファイル + * @see #loadAndPlay(List) loadAndPlay(List<File>) + */ + public void loadAndPlay(File file) { loadAndPlay(Arrays.asList(file)); } + private static final Insets ZERO_INSETS = new Insets(0,0,0,0); private static final Icon deleteIcon = new ButtonIcon(ButtonIcon.X_ICON); /** @@ -243,13 +235,13 @@ public class MidiSequenceEditor extends JDialog { /** * MIDIイベント入力ダイアログ(イベント入力とイベント送出で共用) */ - public MidiEventDialog eventDialog = new MidiEventDialog(); + public MidiEventDialog eventDialog = new MidiEventDialog(); /** * プレイリストビュー(シーケンスリスト) */ public class SequenceListTable extends JTable { /** - * ファイル選択ダイアログ(アプレットでは使用不可) + * ファイル選択ダイアログ(アプレットの場合は使用不可なのでnull) */ private MidiFileChooser midiFileChooser; /** @@ -308,9 +300,7 @@ public class MidiSequenceEditor extends JDialog { for( PlaylistTableModel.Column c : PlaylistTableModel.Column.values() ) { TableColumn tc = colModel.getColumn(c.ordinal()); tc.setPreferredWidth(c.preferredWidth); - if( c == PlaylistTableModel.Column.LENGTH ) { - lengthColumn = tc; - } + if( c == PlaylistTableModel.Column.LENGTH ) lengthColumn = tc; } } private TableColumn lengthColumn; @@ -330,9 +320,7 @@ public class MidiSequenceEditor extends JDialog { // 列モデルからではヘッダタイトルが再描画されないことがある。 // そこで、ヘッダビューから repaint() で突っついて再描画させる。 JTableHeader th = getTableHeader(); - if( th != null ) { - th.repaint(); - } + if( th != null ) th.repaint(); } /** * 時間位置表示セルエディタ(ダブルクリック専用) @@ -382,9 +370,10 @@ public class MidiSequenceEditor extends JDialog { { private JToggleButton playButton = new JToggleButton( getModel().sequencerModel.startStopAction - ); + ) { + { setMargin(ZERO_INSETS); } + }; public PlayButtonCellEditor() { - playButton.setMargin(ZERO_INSETS); int column = PlaylistTableModel.Column.PLAY.ordinal(); TableColumn tc = getColumnModel().getColumn(column); tc.setCellRenderer(this); @@ -402,25 +391,20 @@ public class MidiSequenceEditor extends JDialog { */ @Override public boolean isCellEditable(EventObject e) { - if( ! (e instanceof MouseEvent) ) { - // マウスイベント以外はデフォルトメソッドにお任せ - return super.isCellEditable(e); - } + // マウスイベント以外はデフォルトメソッドにお任せ + if( ! (e instanceof MouseEvent) ) return super.isCellEditable(e); fireEditingStopped(); MouseEvent me = (MouseEvent)e; + // // クリックされたセルの行を特定 int row = rowAtPoint(me.getPoint()); - if( row < 0 ) - return false; + if( row < 0 ) return false; PlaylistTableModel model = getModel(); - if( row >= model.getRowCount() ) - return false; - if( model.sequenceList.get(row).isOnSequencer() ) { - // プレイボタン表示中のセルはシングルクリックでもOK - return true; - } - // プレイボタンのないセルはダブルクリックのみを受け付ける - return me.getClickCount() == 2; + if( row >= model.getRowCount() ) return false; + // + // セル内にプレイボタンがあれば、シングルクリックを受け付ける。 + // プレイボタンのないセルは、ダブルクリックのみ受け付ける。 + return model.sequenceList.get(row).isOnSequencer() || me.getClickCount() == 2; } @Override public Object getCellEditorValue() { return null; } @@ -439,9 +423,7 @@ public class MidiSequenceEditor extends JDialog { ) { fireEditingStopped(); PlaylistTableModel model = getModel(); - if( model.sequenceList.get(row).isOnSequencer() ) { - return playButton; - } + if( model.sequenceList.get(row).isOnSequencer() ) return playButton; model.loadToSequencer(row); return null; } @@ -465,9 +447,7 @@ public class MidiSequenceEditor extends JDialog { * @return プレイリストモデル */ @Override - public PlaylistTableModel getModel() { - return (PlaylistTableModel) super.getModel(); - } + public PlaylistTableModel getModel() { return (PlaylistTableModel)super.getModel(); } /** * シーケンスを削除するアクション */ @@ -479,22 +459,13 @@ public class MidiSequenceEditor extends JDialog { public void actionPerformed(ActionEvent e) { PlaylistTableModel model = getModel(); if( midiFileChooser != null ) { - // ファイルに保存できる場合(Javaアプレットではなく、Javaアプリとして動作している場合) - // - SequenceTrackListTableModel seqModel = model.getSelectedSequenceModel(); - if( seqModel.isModified() ) { - // ファイル未保存の変更がある場合 - // + if( model.getSelectedSequenceModel().isModified() ) { String message = "Selected MIDI sequence not saved - delete it ?\n" + "選択したMIDIシーケンスはまだ保存されていません。削除しますか?"; - if( ! confirm(message) ) { - // 実は削除してほしくなかった場合 - return; - } + if( ! confirm(message) ) return; } } - // 削除を実行 model.removeSelectedSequence(); } }; @@ -503,10 +474,7 @@ public class MidiSequenceEditor extends JDialog { */ private class MidiFileChooser extends JFileChooser { { - String description = "MIDI sequence (*.mid)"; - String extension = "mid"; - FileFilter filter = new FileNameExtensionFilter(description, extension); - setFileFilter(filter); + setFileFilter(new FileNameExtensionFilter("MIDI sequence (*.mid)", "mid")); } /** * ファイル保存アクション @@ -516,32 +484,17 @@ public class MidiSequenceEditor extends JDialog { "Save selected MIDI sequence to file - 選択したMIDIシーケンスをファイルに保存" ) { @Override - public void actionPerformed(ActionEvent e) { - PlaylistTableModel model = getModel(); - SequenceTrackListTableModel sequenceModel = model.getSelectedSequenceModel(); - String filename = sequenceModel.getFilename(); - File selectedFile; - if( filename != null && ! filename.isEmpty() ) { - // プレイリスト上でファイル名が入っていたら、それを初期選択 - setSelectedFile(selectedFile = new File(filename)); - } - int saveOption = showSaveDialog(MidiSequenceEditor.this); - if( saveOption != JFileChooser.APPROVE_OPTION ) { - // 保存ダイアログでキャンセルされた場合 - return; - } - if( (selectedFile = getSelectedFile()).exists() ) { - // 指定されたファイルがすでにあった場合 - String fn = selectedFile.getName(); - String message = "Overwrite " + fn + " ?\n"; - message += fn + " を上書きしてよろしいですか?"; - if( ! confirm(message) ) { - // 上書きしてほしくなかった場合 - return; - } + public void actionPerformed(ActionEvent event) { + SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel(); + String fn = sequenceModel.getFilename(); + if( fn != null && ! fn.isEmpty() ) setSelectedFile(new File(fn)); + if( showSaveDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return; + File f = getSelectedFile(); + if( f.exists() ) { + fn = f.getName(); + if( ! confirm("Overwrite " + fn + " ?\n" + fn + " を上書きしてよろしいですか?") ) return; } - // 保存を実行 - try ( FileOutputStream out = new FileOutputStream(selectedFile) ) { + try ( FileOutputStream out = new FileOutputStream(f) ) { out.write(sequenceModel.getMIDIdata()); sequenceModel.setModified(false); } @@ -555,23 +508,11 @@ public class MidiSequenceEditor extends JDialog { * ファイルを開くアクション */ public Action openMidiFileAction = new AbstractAction("Open") { - { - String tooltip = "Open MIDI file - MIDIファイルを開く"; - putValue(Action.SHORT_DESCRIPTION, tooltip); - } + { putValue(Action.SHORT_DESCRIPTION, "Open MIDI file - MIDIファイルを開く"); } @Override public void actionPerformed(ActionEvent event) { - int openOption = showOpenDialog(MidiSequenceEditor.this); - if(openOption == JFileChooser.APPROVE_OPTION) { - try { - getModel().addSequence(getSelectedFile()); - } catch( IOException|InvalidMidiDataException e ) { - showWarning(e.getMessage()); - } catch( AccessControlException e ) { - showError(e.getMessage()); - e.printStackTrace(); - } - } + if( showOpenDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return; + loadAndPlay(getSelectedFile()); } }; }; @@ -593,8 +534,7 @@ public class MidiSequenceEditor extends JDialog { TableColumn tc = getColumnModel().getColumn(colIndex); tc.setCellEditor(new DefaultCellEditor(new JComboBox(){{ addItem("OFF"); - for(int i=1; i <= MIDISpec.MAX_CHANNELS; i++) - addItem(String.format("%d", i)); + for(int i=1; i <= MIDISpec.MAX_CHANNELS; i++) addItem(String.format("%d", i)); addItem("ALL"); }})); setAutoCreateColumnsFromModel(false); @@ -628,21 +568,17 @@ public class MidiSequenceEditor extends JDialog { public TitleLabel() { setText(TITLE); } @Override public void valueChanged(ListSelectionEvent event) { - if( event.getValueIsAdjusting() ) - return; + if( event.getValueIsAdjusting() ) return; SequenceTrackListTableModel oldModel = getModel(); SequenceTrackListTableModel newModel = oldModel.sequenceListTableModel.getSelectedSequenceModel(); - if( oldModel == newModel ) - return; + if( oldModel == newModel ) return; // // MIDIチャンネル選択中のときはキャンセルする cancelCellEditing(); // int index = oldModel.sequenceListTableModel.sequenceListSelectionModel.getMinSelectionIndex(); String text = TITLE; - if( index >= 0 ) { - text = String.format(text+" - MIDI file No.%d", index); - } + if( index >= 0 ) text = String.format(text+" - MIDI file No.%d", index); setText(text); if( newModel == null ) { newModel = oldModel.sequenceListTableModel.emptyTrackListTableModel; @@ -668,8 +604,7 @@ public class MidiSequenceEditor extends JDialog { private class TrackSelectionListener implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { - if( e != null && e.getValueIsAdjusting() ) - return; + if( e != null && e.getValueIsAdjusting() ) return; ListSelectionModel tlsm = getModel().trackListSelectionModel; deleteTrackAction.setEnabled(! tlsm.isSelectionEmpty()); eventListTable.titleLabel.update(tlsm, getModel()); @@ -693,8 +628,7 @@ public class MidiSequenceEditor extends JDialog { */ private void cancelCellEditing() { TableCellEditor currentCellEditor = getCellEditor(); - if( currentCellEditor != null ) - currentCellEditor.cancelCellEditing(); + if( currentCellEditor != null ) currentCellEditor.cancelCellEditing(); } /** * トラック追加アクション @@ -706,9 +640,7 @@ public class MidiSequenceEditor extends JDialog { setEnabled(false); } @Override - public void actionPerformed(ActionEvent e) { - getModel().createTrack(); - } + public void actionPerformed(ActionEvent e) { getModel().createTrack(); } }; /** * トラック削除アクション @@ -721,8 +653,7 @@ public class MidiSequenceEditor extends JDialog { } @Override public void actionPerformed(ActionEvent e) { - String message = "Do you want to delete selected track ?\n" - + "選択したトラックを削除しますか?"; + String message = "Do you want to delete selected track ?\n選択したトラックを削除しますか?"; if( confirm(message) ) getModel().deleteSelectedTracks(); } }; @@ -869,13 +800,11 @@ public class MidiSequenceEditor extends JDialog { private JToggleButton.ToggleButtonModel pairNoteOnOffModel = new JToggleButton.ToggleButtonModel() { { - addItemListener( - new ItemListener() { - public void itemStateChanged(ItemEvent e) { - eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()); - } + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()); } - ); + }); setSelected(true); } }; @@ -1134,8 +1063,7 @@ public class MidiSequenceEditor extends JDialog { */ @Override public boolean isCellEditable(EventObject e) { - if( ! (e instanceof MouseEvent) ) - return super.isCellEditable(e); + if( ! (e instanceof MouseEvent) ) return super.isCellEditable(e); return ((MouseEvent)e).getClickCount() == 2; } @Override @@ -1210,78 +1138,55 @@ public class MidiSequenceEditor extends JDialog { * @param deviceModelList MIDIデバイスモデルリスト */ public MidiSequenceEditor(MidiSequencerModel sequencerModel) { - // テーブルモデルとテーブルビューの生成 - sequenceListTable = new SequenceListTable( - new PlaylistTableModel(sequencerModel) - ); + sequenceListTable = new SequenceListTable(new PlaylistTableModel(sequencerModel)); trackListTable = new TrackListTable( new SequenceTrackListTableModel(sequenceListTable.getModel(), null, null) ); - eventListTable = new EventListTable( - new TrackEventListTableModel(trackListTable.getModel(), null) - ); - // レイアウト + eventListTable = new EventListTable(new TrackEventListTableModel(trackListTable.getModel(), null)); setTitle("MIDI Editor/Playlist - MIDI Chord Helper"); setBounds( 150, 200, 900, 500 ); setLayout(new FlowLayout()); new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetListener, true); + // + // パネルレイアウト JPanel playlistPanel = new JPanel() {{ JPanel playlistOperationPanel = new JPanel() {{ setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); add(Box.createRigidArea(new Dimension(10, 0))); - add(new JButton(newSequenceDialog.openAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(newSequenceDialog.openAction) {{ setMargin(ZERO_INSETS); }}); if( sequenceListTable.midiFileChooser != null ) { add( Box.createRigidArea(new Dimension(5, 0)) ); - add(new JButton( - sequenceListTable.midiFileChooser.openMidiFileAction - ) {{ + add(new JButton(sequenceListTable.midiFileChooser.openMidiFileAction) {{ setMargin(ZERO_INSETS); }}); } if(sequenceListTable.base64EncodeAction != null) { add(Box.createRigidArea(new Dimension(5, 0))); - add(new JButton(sequenceListTable.base64EncodeAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(sequenceListTable.base64EncodeAction) {{ setMargin(ZERO_INSETS); }}); } add(Box.createRigidArea(new Dimension(5, 0))); PlaylistTableModel playlistTableModel = sequenceListTable.getModel(); - add(new JButton(playlistTableModel.moveToTopAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(playlistTableModel.moveToTopAction) {{ setMargin(ZERO_INSETS); }}); add(Box.createRigidArea(new Dimension(5, 0))); - add(new JButton(playlistTableModel.moveToBottomAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(playlistTableModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }}); if( sequenceListTable.midiFileChooser != null ) { add(Box.createRigidArea(new Dimension(5, 0))); - add(new JButton( - sequenceListTable.midiFileChooser.saveMidiFileAction - ) {{ + add(new JButton(sequenceListTable.midiFileChooser.saveMidiFileAction) {{ setMargin(ZERO_INSETS); }}); } add( Box.createRigidArea(new Dimension(5, 0)) ); - add(new JButton(sequenceListTable.deleteSequenceAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(sequenceListTable.deleteSequenceAction) {{ setMargin(ZERO_INSETS); }}); add( Box.createRigidArea(new Dimension(5, 0)) ); - add(new SequencerSpeedSlider( - playlistTableModel.sequencerModel.speedSliderModel - )); + add(new SequencerSpeedSlider(playlistTableModel.sequencerModel.speedSliderModel)); add( Box.createRigidArea(new Dimension(5, 0)) ); add(new JPanel() {{ + MidiSequencerModel sequencerModel = sequenceListTable.getModel().sequencerModel; add(new JLabel("SyncMode:")); add(new JLabel("Master")); - add(new JComboBox( - sequenceListTable.getModel().sequencerModel.masterSyncModeModel - )); + add(new JComboBox(sequencerModel.masterSyncModeModel)); add(new JLabel("Slave")); - add(new JComboBox( - sequenceListTable.getModel().sequencerModel.slaveSyncModeModel - )); + add(new JComboBox(sequencerModel.slaveSyncModeModel)); }}); }}; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); @@ -1292,12 +1197,8 @@ public class MidiSequenceEditor extends JDialog { }}; JPanel trackListPanel = new JPanel() {{ JPanel trackListOperationPanel = new JPanel() {{ - add(new JButton(trackListTable.addTrackAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(trackListTable.deleteTrackAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(trackListTable.addTrackAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(trackListTable.deleteTrackAction) {{ setMargin(ZERO_INSETS); }}); }}; setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); add(trackListTable.titleLabel); @@ -1312,24 +1213,12 @@ public class MidiSequenceEditor extends JDialog { setModel(eventListTable.pairNoteOnOffModel); setToolTipText("NoteON/OFFをペアで同時選択する"); }}); - add(new JButton(eventListTable.queryJumpEventAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(eventListTable.queryAddEventAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(eventListTable.copyEventAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(eventListTable.cutEventAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(eventListTable.queryPasteEventAction) {{ - setMargin(ZERO_INSETS); - }}); - add(new JButton(eventListTable.deleteEventAction) {{ - setMargin(ZERO_INSETS); - }}); + add(new JButton(eventListTable.queryJumpEventAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(eventListTable.queryAddEventAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(eventListTable.copyEventAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(eventListTable.cutEventAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(eventListTable.queryPasteEventAction) {{ setMargin(ZERO_INSETS); }}); + add(new JButton(eventListTable.deleteEventAction) {{ setMargin(ZERO_INSETS); }}); }}; setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(eventListTable.titleLabel); diff --git a/src/camidion/chordhelper/midieditor/PlaylistTableModel.java b/src/camidion/chordhelper/midieditor/PlaylistTableModel.java index db1e895..6bd4e12 100644 --- a/src/camidion/chordhelper/midieditor/PlaylistTableModel.java +++ b/src/camidion/chordhelper/midieditor/PlaylistTableModel.java @@ -410,9 +410,7 @@ public class PlaylistTableModel extends AbstractTableModel { * @return 未保存の修正内容を持つシーケンスがあればtrue */ public boolean isModified() { - for( SequenceTrackListTableModel m : sequenceList ) { - if( m.isModified() ) return true; - } + for( SequenceTrackListTableModel m : sequenceList ) if( m.isModified() ) return true; return false; } /** @@ -448,8 +446,7 @@ public class PlaylistTableModel extends AbstractTableModel { */ public void fireSequenceModified(SequenceTrackListTableModel sequenceTableModel) { int index = sequenceList.indexOf(sequenceTableModel); - if( index < 0 ) - return; + if( index < 0 ) return; sequenceTableModel.setModified(true); fireTableRowsUpdated(index, index); } @@ -511,9 +508,7 @@ public class PlaylistTableModel extends AbstractTableModel { * @return 追加されたシーケンスのインデックス(先頭が 0) */ public int addSequence(Sequence sequence, String filename) { - sequenceList.add( - new SequenceTrackListTableModel(this, sequence, filename) - ); + sequenceList.add( new SequenceTrackListTableModel(this, sequence, filename) ); int lastIndex = sequenceList.size() - 1; fireTableRowsInserted(lastIndex, lastIndex); return lastIndex; @@ -553,14 +548,11 @@ public class PlaylistTableModel extends AbstractTableModel { * @throws InvalidMidiDataException ファイル内のMIDIデータが正しくない場合 * @throws IOException ファイル入出力に失敗した場合 */ - public int addSequences(List fileList) - throws InvalidMidiDataException, IOException - { + public int addSequences(List fileList) throws InvalidMidiDataException, IOException { int firstIndex = -1; for( File file : fileList ) { int lastIndex = addSequence(file); - if( firstIndex == -1 ) - firstIndex = lastIndex; + if( firstIndex == -1 ) firstIndex = lastIndex; } return firstIndex; } @@ -575,50 +567,43 @@ public class PlaylistTableModel extends AbstractTableModel { public int addSequenceFromURL(String midiFileUrl) throws URISyntaxException, IOException, InvalidMidiDataException { - URI uri = new URI(midiFileUrl); - URL url = uri.toURL(); - Sequence seq = MidiSystem.getSequence(url); - String filename = url.getFile().replaceFirst("^.*/",""); - return addSequence(seq, filename); + URL url = (new URI(midiFileUrl)).toURL(); + return addSequence(MidiSystem.getSequence(url), url.getFile().replaceFirst("^.*/","")); } /** - * 選択したシーケンスを除去します。 - * @param listSelectionModel 選択状態 + * 選択されたシーケンスを除去します。 + * 除去されたシーケンスがシーケンサーにロード済みの場合、アンロードします。 */ public void removeSelectedSequence() { - if( sequenceListSelectionModel.isSelectionEmpty() ) - return; + if( sequenceListSelectionModel.isSelectionEmpty() ) return; int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex(); - if( sequenceList.remove(selectedIndex).isOnSequencer() ) { - // 削除したシーケンスが - // シーケンサーにロード済みだった場合、アンロードする。 + if( sequenceList.remove(selectedIndex).isOnSequencer() ) sequencerModel.setSequenceTrackListTableModel(null); - } fireTableRowsDeleted(selectedIndex, selectedIndex); } /** * 指定したインデックス位置のシーケンスをシーケンサーにロードします。 + * すでに同じIDのシーケンスがロードされていた場合はスキップします。 * @param index シーケンスのインデックス位置(-1 を指定するとアンロードされます) */ public void loadToSequencer(int index) { SequenceTrackListTableModel oldSeq = sequencerModel.getSequenceTrackListTableModel(); SequenceTrackListTableModel newSeq = (index < 0 ? null : sequenceList.get(index)); - if(oldSeq == newSeq) - return; + if(oldSeq == newSeq) return; sequencerModel.setSequenceTrackListTableModel(newSeq); + // + // 変更点をテーブルビューに通知して再表示してもらう int columnIndices[] = { Column.PLAY.ordinal(), Column.POSITION.ordinal(), }; if( oldSeq != null ) { int oldIndex = sequenceList.indexOf(oldSeq); - for( int columnIndex : columnIndices ) - fireTableCellUpdated(oldIndex, columnIndex); + for( int columnIndex : columnIndices ) fireTableCellUpdated(oldIndex, columnIndex); } if( newSeq != null ) { - for( int columnIndex : columnIndices ) - fireTableCellUpdated(index, columnIndex); + for( int columnIndex : columnIndices ) fireTableCellUpdated(index, columnIndex); } } /** @@ -637,9 +622,8 @@ public class PlaylistTableModel extends AbstractTableModel { 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 >= sequenceList.size() ) return false; loadToSequencer(index); return true; } -} \ No newline at end of file +} -- 2.11.0