From: Akiyoshi Kamide Date: Thu, 27 Apr 2017 16:53:44 +0000 (+0900) Subject: 曲選択動作の見直し X-Git-Url: http://git.osdn.net/view?p=midichordhelper%2FMIDIChordHelper.git;a=commitdiff_plain;h=77ad76c83254d59ac33c528127bca6fa80b886fa 曲選択動作の見直し --- diff --git a/src/camidion/chordhelper/ChordHelperApplet.java b/src/camidion/chordhelper/ChordHelperApplet.java index 6ce9f19..1c683a3 100644 --- a/src/camidion/chordhelper/ChordHelperApplet.java +++ b/src/camidion/chordhelper/ChordHelperApplet.java @@ -143,9 +143,7 @@ public class ChordHelperApplet extends JApplet { /** * プレイリスト上で現在選択されているMIDIシーケンスをシーケンサへロードして再生します。 */ - public void play() { - play(playlistModel.getSelectionModel().getMinSelectionIndex()); - } + public void play() { midiEditor.play(); } /** * 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスをシーケンサへロードして再生します。 * @param index インデックス値(0から始まる) @@ -266,7 +264,7 @@ public class ChordHelperApplet extends JApplet { */ public static class VersionInfo { public static final String NAME = "MIDI Chord Helper"; - public static final String VERSION = "Ver.20170423.1"; + public static final String VERSION = "Ver.20170427.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/"; diff --git a/src/camidion/chordhelper/midieditor/MidiEventTable.java b/src/camidion/chordhelper/midieditor/MidiEventTable.java index 0f75ec0..3dbf94b 100644 --- a/src/camidion/chordhelper/midieditor/MidiEventTable.java +++ b/src/camidion/chordhelper/midieditor/MidiEventTable.java @@ -23,7 +23,6 @@ import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToggleButton; -import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellEditor; import javax.swing.table.TableModel; @@ -46,7 +45,7 @@ public class MidiEventTable extends JTable { * @param outputMidiDevice 操作音出力先MIDIデバイス */ public MidiEventTable(MidiEventTableModel model, MidiEventDialog eventDialog, VirtualMidiDevice outputMidiDevice) { - super(model, null, model.getSelectionModel()); + super(model); this.outputMidiDevice = outputMidiDevice; this.eventDialog = eventDialog; titleLabel = new TitleLabel(); @@ -61,7 +60,7 @@ public class MidiEventTable extends JTable { }; eventCellEditor = new MidiEventCellEditor(); setAutoCreateColumnsFromModel(false); - selectionModel.addListSelectionListener(selectionListener = event->{ + selectionModel.addListSelectionListener(event->{ if( event.getValueIsAdjusting() ) return; if( selectionModel.isSelectionEmpty() ) { queryPasteEventAction.setEnabled(false); @@ -113,10 +112,6 @@ public class MidiEventTable extends JTable { */ private VirtualMidiDevice outputMidiDevice; /** - * イベント選択リスナー - */ - private ListSelectionListener selectionListener; - /** * このテーブルビューが表示するデータを提供するトラック(イベントリスト)データモデルを返します。 * @return トラック(イベントリスト)データモデル */ @@ -131,8 +126,7 @@ public class MidiEventTable extends JTable { public void setModel(MidiEventTableModel model) { if( dataModel == model ) return; if( model == null ) { - PlaylistTableModel playlist = getModel().getParent().getParent(); - model = playlist.emptyEventListTableModel; + model = getModel().getParent().getParent().emptyEventListTableModel; queryJumpEventAction.setEnabled(false); queryAddEventAction.setEnabled(false); @@ -145,11 +139,7 @@ public class MidiEventTable extends JTable { queryJumpEventAction.setEnabled(true); queryAddEventAction.setEnabled(true); } - selectionModel.removeListSelectionListener(selectionListener); super.setModel(model); - setSelectionModel(model.getSelectionModel()); - titleLabel.updateTrackNumber(model.getParent().getSelectionModel().getMinSelectionIndex()); - selectionModel.addListSelectionListener(selectionListener); } /** * タイトルラベル @@ -162,7 +152,7 @@ public class MidiEventTable extends JTable { class TitleLabel extends JLabel { private static final String TITLE = "MIDI Events"; private TitleLabel() { super(TITLE); } - void updateTrackNumber(int index) { + void showTrackNumber(int index) { String text = TITLE; if( index >= 0 ) text = String.format(TITLE+" - track #%d", index); setText(text); diff --git a/src/camidion/chordhelper/midieditor/MidiEventTableModel.java b/src/camidion/chordhelper/midieditor/MidiEventTableModel.java index dc57c63..b953219 100644 --- a/src/camidion/chordhelper/midieditor/MidiEventTableModel.java +++ b/src/camidion/chordhelper/midieditor/MidiEventTableModel.java @@ -9,7 +9,6 @@ import javax.sound.midi.MidiMessage; import javax.sound.midi.Sequencer; import javax.sound.midi.ShortMessage; import javax.sound.midi.Track; -import javax.swing.DefaultListSelectionModel; import javax.swing.ListSelectionModel; import javax.swing.table.AbstractTableModel; @@ -113,15 +112,6 @@ public class MidiEventTableModel extends AbstractTableModel { return sequenceTrackListTableModel; } /** - * 選択状態を返します。 - */ - public ListSelectionModel getSelectionModel() { return selectionModel; } - private ListSelectionModel selectionModel = new DefaultListSelectionModel() { - { - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - } - }; - /** * シーケンスを親にして、その特定のトラックに連動する * MIDIトラックモデルを構築します。 * diff --git a/src/camidion/chordhelper/midieditor/MidiSequenceEditorDialog.java b/src/camidion/chordhelper/midieditor/MidiSequenceEditorDialog.java index e9e697f..234045c 100644 --- a/src/camidion/chordhelper/midieditor/MidiSequenceEditorDialog.java +++ b/src/camidion/chordhelper/midieditor/MidiSequenceEditorDialog.java @@ -112,6 +112,13 @@ public class MidiSequenceEditorDialog extends JDialog { JOptionPane.showMessageDialog(this, e, ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE); } } + /** + * 現在選択されているMIDIシーケンスから再生します。 + * すでに再生されていた場合、このエディタダイアログを表示します。 + */ + public void play() { + play(playlistTable.getSelectionModel().getMinSelectionIndex()); + } static final Icon deleteIcon = new ButtonIcon(ButtonIcon.X_ICON); /** diff --git a/src/camidion/chordhelper/midieditor/NewSequenceDialog.java b/src/camidion/chordhelper/midieditor/NewSequenceDialog.java index f089410..8eef34e 100644 --- a/src/camidion/chordhelper/midieditor/NewSequenceDialog.java +++ b/src/camidion/chordhelper/midieditor/NewSequenceDialog.java @@ -103,7 +103,8 @@ public class NewSequenceDialog extends JDialog { @Override public void actionPerformed(ActionEvent event) { try { - playlist.getSequenceModelList().get(playlist.play(getMidiSequence())).setModified(true); + int index = playlist.play(getMidiSequence()); + playlist.getSequenceModelList().get(index).setModified(true); } catch (Exception ex) { JOptionPane.showMessageDialog( NewSequenceDialog.this, ex, diff --git a/src/camidion/chordhelper/midieditor/PlaylistTable.java b/src/camidion/chordhelper/midieditor/PlaylistTable.java index 9866963..276e58c 100644 --- a/src/camidion/chordhelper/midieditor/PlaylistTable.java +++ b/src/camidion/chordhelper/midieditor/PlaylistTable.java @@ -21,6 +21,7 @@ import javax.swing.AbstractAction; import javax.swing.AbstractCellEditor; import javax.swing.Action; import javax.swing.DefaultCellEditor; +import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -29,6 +30,9 @@ import javax.swing.JOptionPane; import javax.swing.JRootPane; import javax.swing.JTable; import javax.swing.JToggleButton; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.JTableHeader; @@ -53,13 +57,49 @@ public class PlaylistTable extends JTable { /** MIDIデバイスダイアログを開くアクション */ private Action midiDeviceDialogOpenAction; /** + * 選択されたMIDIシーケンスのテーブルモデルを返します。 + * @return 選択されたMIDIシーケンスのテーブルモデル(非選択時はnull) + */ + private SequenceTrackListTableModel getSelectedSequenceModel() { + if( selectionModel.isSelectionEmpty() ) return null; + int selectedIndex = selectionModel.getMinSelectionIndex(); + List list = getModel().getSequenceModelList(); + return selectedIndex >= list.size() ? null : list.get(selectedIndex); + } + /** + * 行が選択されているときだけイネーブルになるアクション + */ + private abstract class SelectedSequenceAction extends AbstractAction implements ListSelectionListener { + public SelectedSequenceAction(String name, Icon icon, String tooltip) { + super(name,icon); init(tooltip); + } + public SelectedSequenceAction(String name, String tooltip) { + super(name); init(tooltip); + } + @Override + public void valueChanged(ListSelectionEvent e) { + if( e.getValueIsAdjusting() ) return; + setEnebledBySelection(); + } + protected void setEnebledBySelection() { + int index = selectionModel.getMinSelectionIndex(); + setEnabled(index >= 0); + } + private void init(String tooltip) { + putValue(Action.SHORT_DESCRIPTION, tooltip); + selectionModel.addListSelectionListener(this); + setEnebledBySelection(); + } + } + /** * プレイリストビューを構築します。 * @param model プレイリストデータモデル * @param midiDeviceDialogOpenAction MIDIデバイスダイアログを開くアクション * @param trackListTable トラックリストテーブル(子テーブル) */ public PlaylistTable(PlaylistTableModel model, Action midiDeviceDialogOpenAction, SequenceTrackListTable trackListTable) { - super(model, null, model.getSelectionModel()); + super(model); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); this.midiDeviceDialogOpenAction = midiDeviceDialogOpenAction; try { midiFileChooser = new MidiFileChooser(); @@ -89,7 +129,7 @@ public class PlaylistTable extends JTable { } @Override public void actionPerformed(ActionEvent e) { - SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel(); + SequenceTrackListTableModel sequenceModel = getSelectedSequenceModel(); byte[] data = null; String filename = null; if( sequenceModel != null ) { @@ -114,7 +154,8 @@ public class PlaylistTable extends JTable { }); selectionModel.addListSelectionListener(event->{ if( event.getValueIsAdjusting() ) return; - trackListTable.setModel(getModel().getSelectedSequenceModel()); + trackListTable.setModel(getSelectedSequenceModel()); + trackListTable.titleLabel.showMidiFileNumber(selectionModel); }); } private TableColumn lengthColumn; @@ -280,13 +321,12 @@ public class PlaylistTable extends JTable { * @return 追加されたMIDIファイルのインデックス値(先頭が0、追加されなかった場合は-1) */ public int add(List fileList) { - PlaylistTableModel model = getModel(); int firstIndex = -1; Iterator itr = fileList.iterator(); while(itr.hasNext()) { File file = itr.next(); try (FileInputStream in = new FileInputStream(file)) { - int lastIndex = model.add(MidiSystem.getSequence(in), file.getName()); + int lastIndex = ((PlaylistTableModel)dataModel).add(MidiSystem.getSequence(in), file.getName()); if( firstIndex < 0 ) firstIndex = lastIndex; } catch(IOException|InvalidMidiDataException e) { String message = "Could not open as MIDI file "+file+"\n"+e; @@ -316,7 +356,7 @@ public class PlaylistTable extends JTable { /** * シーケンスを削除するアクション */ - Action deleteSequenceAction = getModel().new SelectedSequenceAction( + Action deleteSequenceAction = new SelectedSequenceAction( "Delete", MidiSequenceEditorDialog.deleteIcon, "Delete selected MIDI sequence - 選択した曲をプレイリストから削除" ) { @@ -327,8 +367,8 @@ public class PlaylistTable extends JTable { public void actionPerformed(ActionEvent event) { PlaylistTableModel model = getModel(); if( midiFileChooser != null ) { - SequenceTrackListTableModel seqModel = model.getSelectedSequenceModel(); - if( seqModel != null && seqModel.isModified() && JOptionPane.showConfirmDialog( + SequenceTrackListTableModel sequenceModel = getSelectedSequenceModel(); + if( sequenceModel != null && sequenceModel.isModified() && JOptionPane.showConfirmDialog( ((JComponent)event.getSource()).getRootPane(), CONFIRM_MESSAGE, ChordHelperApplet.VersionInfo.NAME, @@ -336,8 +376,8 @@ public class PlaylistTable extends JTable { JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION ) return; } - if( ! model.getSelectionModel().isSelectionEmpty() ) try { - model.remove(model.getSelectionModel().getMinSelectionIndex()); + if( ! selectionModel.isSelectionEmpty() ) try { + model.remove(selectionModel.getMinSelectionIndex()); } catch (Exception ex) { JOptionPane.showMessageDialog( ((JComponent)event.getSource()).getRootPane(), ex, @@ -354,13 +394,13 @@ public class PlaylistTable extends JTable { /** * ファイル保存アクション */ - public Action saveMidiFileAction = getModel().new SelectedSequenceAction( + public Action saveMidiFileAction = new SelectedSequenceAction( "Save", "Save selected MIDI sequence to file - 選択したMIDIシーケンスをファイルに保存" ) { @Override public void actionPerformed(ActionEvent event) { - SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel(); + SequenceTrackListTableModel sequenceModel = getSelectedSequenceModel(); if( sequenceModel == null ) return; String fn = sequenceModel.getFilename(); if( fn != null && ! fn.isEmpty() ) setSelectedFile(new File(fn)); diff --git a/src/camidion/chordhelper/midieditor/PlaylistTableModel.java b/src/camidion/chordhelper/midieditor/PlaylistTableModel.java index 1aca48c..f265683 100644 --- a/src/camidion/chordhelper/midieditor/PlaylistTableModel.java +++ b/src/camidion/chordhelper/midieditor/PlaylistTableModel.java @@ -13,14 +13,9 @@ import javax.sound.midi.Sequence; import javax.sound.midi.Sequencer; import javax.swing.AbstractAction; import javax.swing.Action; -import javax.swing.DefaultListSelectionModel; -import javax.swing.Icon; -import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; @@ -46,15 +41,6 @@ public class PlaylistTableModel extends AbstractTableModel { */ public final MidiEventTableModel emptyEventListTableModel = new MidiEventTableModel(emptyTrackListTableModel, null); /** - * このプレイリストの選択モデルを返します。 - */ - public ListSelectionModel getSelectionModel() { return selectionModel; } - private ListSelectionModel selectionModel = new DefaultListSelectionModel() { - { - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - } - }; - /** * テーブルモデルの変更を示すイベントが、ファイル名の変更によるものかどうかをチェックします。 * @param event テーブルモデルの変更を示すイベント * @return ファイル名の変更による場合true @@ -138,31 +124,6 @@ public class PlaylistTableModel extends AbstractTableModel { return sequenceModelList; } /** - * 行が選択されているときだけイネーブルになるアクション - */ - public abstract class SelectedSequenceAction extends AbstractAction implements ListSelectionListener { - public SelectedSequenceAction(String name, Icon icon, String tooltip) { - super(name,icon); init(tooltip); - } - public SelectedSequenceAction(String name, String tooltip) { - super(name); init(tooltip); - } - @Override - public void valueChanged(ListSelectionEvent e) { - if( e.getValueIsAdjusting() ) return; - setEnebledBySelection(); - } - protected void setEnebledBySelection() { - int index = selectionModel.getMinSelectionIndex(); - setEnabled(index >= 0); - } - private void init(String tooltip) { - putValue(Action.SHORT_DESCRIPTION, tooltip); - selectionModel.addListSelectionListener(this); - setEnebledBySelection(); - } - } - /** * 繰り返し再生ON/OFF切り替えアクション */ public Action getToggleRepeatAction() { return toggleRepeatAction; } @@ -381,16 +342,6 @@ public class PlaylistTableModel extends AbstractTableModel { return (int)(sequenceModelList.stream().mapToLong(m -> m.getMicrosecondLength() / 1000L).sum() / 1000L); } /** - * 選択されたMIDIシーケンスのテーブルモデルを返します。 - * @return 選択されたMIDIシーケンスのテーブルモデル(非選択時はnull) - */ - public SequenceTrackListTableModel getSelectedSequenceModel() { - if( selectionModel.isSelectionEmpty() ) return null; - int selectedIndex = selectionModel.getMinSelectionIndex(); - if( selectedIndex >= sequenceModelList.size() ) return null; - return sequenceModelList.get(selectedIndex); - } - /** * MIDIシーケンスを追加します。 * @param sequence MIDIシーケンス(nullの場合、シーケンスを自動生成して追加) * @param filename ファイル名(nullの場合、ファイル名なし) @@ -401,7 +352,6 @@ public class PlaylistTableModel extends AbstractTableModel { sequenceModelList.add(new SequenceTrackListTableModel(this, sequence, filename)); int lastIndex = sequenceModelList.size() - 1; fireTableRowsInserted(lastIndex, lastIndex); - selectionModel.setSelectionInterval(lastIndex, lastIndex); return lastIndex; } /** diff --git a/src/camidion/chordhelper/midieditor/SequenceTrackListTable.java b/src/camidion/chordhelper/midieditor/SequenceTrackListTable.java index 4409e9e..65bf5d7 100644 --- a/src/camidion/chordhelper/midieditor/SequenceTrackListTable.java +++ b/src/camidion/chordhelper/midieditor/SequenceTrackListTable.java @@ -12,7 +12,6 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; -import javax.swing.event.ListSelectionListener; import javax.swing.event.TableModelEvent; import javax.swing.table.TableCellEditor; @@ -65,7 +64,7 @@ public class SequenceTrackListTable extends JTable { * @param eventListTable イベントリストテーブル */ public SequenceTrackListTable(SequenceTrackListTableModel model, MidiEventTable eventListTable) { - super(model, null, model.getSelectionModel()); + super(model); getColumnModel() .getColumn(SequenceTrackListTableModel.Column.RECORD_CHANNEL.ordinal()) .setCellEditor(new DefaultCellEditor(new JComboBox(){{ @@ -77,17 +76,14 @@ public class SequenceTrackListTable extends JTable { Arrays.stream(SequenceTrackListTableModel.Column.values()).forEach(c-> getColumnModel().getColumn(c.ordinal()).setPreferredWidth(c.preferredWidth) ); - selectionModel.addListSelectionListener(selectionListener = event->{ + selectionModel.addListSelectionListener(event->{ if( event.getValueIsAdjusting() ) return; deleteTrackAction.setEnabled(! selectionModel.isSelectionEmpty()); - eventListTable.setModel(getModel().getSelectedTrackModel()); + eventListTable.setModel(getModel().getSelectedTrackModel(selectionModel)); + eventListTable.titleLabel.showTrackNumber(selectionModel.getMinSelectionIndex()); }); } /** - * トラック選択リスナー - */ - private ListSelectionListener selectionListener; - /** * このテーブルビューが表示するデータを提供するシーケンス(トラックリスト)データモデルを返します。 * @return シーケンス(トラックリスト)データモデル */ @@ -109,12 +105,7 @@ public class SequenceTrackListTable extends JTable { else { addTrackAction.setEnabled(true); } - selectionModel.clearSelection(); - selectionModel.removeListSelectionListener(selectionListener); super.setModel(model); - setSelectionModel(model.getSelectionModel()); - titleLabel.setSelection(model.getParent().getSelectionModel()); - selectionModel.addListSelectionListener(selectionListener); } /** * 曲番号表示付きタイトルラベル @@ -123,10 +114,10 @@ public class SequenceTrackListTable extends JTable { /** * 曲番号表示付きタイトルラベル */ - private class TitleLabel extends JLabel { + class TitleLabel extends JLabel { private static final String TITLE = "Tracks"; public TitleLabel() { setText(TITLE); } - public void setSelection(ListSelectionModel sequenceSelectionModel) { + public void showMidiFileNumber(ListSelectionModel sequenceSelectionModel) { String text = TITLE; if( ! sequenceSelectionModel.isSelectionEmpty() ) { int index = sequenceSelectionModel.getMinSelectionIndex(); diff --git a/src/camidion/chordhelper/midieditor/SequenceTrackListTableModel.java b/src/camidion/chordhelper/midieditor/SequenceTrackListTableModel.java index b712467..8a9fe9b 100644 --- a/src/camidion/chordhelper/midieditor/SequenceTrackListTableModel.java +++ b/src/camidion/chordhelper/midieditor/SequenceTrackListTableModel.java @@ -9,7 +9,6 @@ import java.util.List; import javax.sound.midi.MidiSystem; import javax.sound.midi.Sequence; import javax.sound.midi.Track; -import javax.swing.DefaultListSelectionModel; import javax.swing.ListSelectionModel; import javax.swing.table.AbstractTableModel; @@ -83,15 +82,6 @@ public class SequenceTrackListTableModel extends AbstractTableModel { */ private List trackModelList = new ArrayList<>(); /** - * このトラックリストの選択モデルを返します。 - */ - public ListSelectionModel getSelectionModel() { return selectionModel; } - private ListSelectionModel selectionModel = new DefaultListSelectionModel(){ - { - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - } - }; - /** * MIDIシーケンスとファイル名から {@link SequenceTrackListTableModel} を構築します。 * @param sequenceListTableModel 親のプレイリスト * @param sequence MIDIシーケンス @@ -337,7 +327,7 @@ public class SequenceTrackListTableModel extends AbstractTableModel { * @param index トラックのインデックス * @return トラックモデル(見つからない場合null) */ - public MidiEventTableModel getSelectedTrackModel() { + public MidiEventTableModel getSelectedTrackModel(ListSelectionModel selectionModel) { if( selectionModel.isSelectionEmpty() ) return null; Track tracks[] = sequence.getTracks(); if( tracks.length == 0 ) return null;