/**
* プレイリスト上で現在選択されているMIDIシーケンスをシーケンサへロードして再生します。
*/
- public void play() {
- play(playlistModel.getSelectionModel().getMinSelectionIndex());
- }
+ public void play() { midiEditor.play(); }
/**
* 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスをシーケンサへロードして再生します。
* @param index インデックス値(0から始まる)
*/
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/";
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;
* @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();
};
eventCellEditor = new MidiEventCellEditor();
setAutoCreateColumnsFromModel(false);
- selectionModel.addListSelectionListener(selectionListener = event->{
+ selectionModel.addListSelectionListener(event->{
if( event.getValueIsAdjusting() ) return;
if( selectionModel.isSelectionEmpty() ) {
queryPasteEventAction.setEnabled(false);
*/
private VirtualMidiDevice outputMidiDevice;
/**
- * イベント選択リスナー
- */
- private ListSelectionListener selectionListener;
- /**
* このテーブルビューが表示するデータを提供するトラック(イベントリスト)データモデルを返します。
* @return トラック(イベントリスト)データモデル
*/
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);
queryJumpEventAction.setEnabled(true);
queryAddEventAction.setEnabled(true);
}
- selectionModel.removeListSelectionListener(selectionListener);
super.setModel(model);
- setSelectionModel(model.getSelectionModel());
- titleLabel.updateTrackNumber(model.getParent().getSelectionModel().getMinSelectionIndex());
- selectionModel.addListSelectionListener(selectionListener);
}
/**
* タイトルラベル
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);
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;
return sequenceTrackListTableModel;
}
/**
- * 選択状態を返します。
- */
- public ListSelectionModel getSelectionModel() { return selectionModel; }
- private ListSelectionModel selectionModel = new DefaultListSelectionModel() {
- {
- setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
- }
- };
- /**
* シーケンスを親にして、その特定のトラックに連動する
* MIDIトラックモデルを構築します。
*
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);
/**
@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,
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;
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;
/** MIDIデバイスダイアログを開くアクション */
private Action midiDeviceDialogOpenAction;
/**
+ * 選択されたMIDIシーケンスのテーブルモデルを返します。
+ * @return 選択されたMIDIシーケンスのテーブルモデル(非選択時はnull)
+ */
+ private SequenceTrackListTableModel getSelectedSequenceModel() {
+ if( selectionModel.isSelectionEmpty() ) return null;
+ int selectedIndex = selectionModel.getMinSelectionIndex();
+ List<SequenceTrackListTableModel> 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();
}
@Override
public void actionPerformed(ActionEvent e) {
- SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel();
+ SequenceTrackListTableModel sequenceModel = getSelectedSequenceModel();
byte[] data = null;
String filename = null;
if( sequenceModel != null ) {
});
selectionModel.addListSelectionListener(event->{
if( event.getValueIsAdjusting() ) return;
- trackListTable.setModel(getModel().getSelectedSequenceModel());
+ trackListTable.setModel(getSelectedSequenceModel());
+ trackListTable.titleLabel.showMidiFileNumber(selectionModel);
});
}
private TableColumn lengthColumn;
* @return 追加されたMIDIファイルのインデックス値(先頭が0、追加されなかった場合は-1)
*/
public int add(List<File> fileList) {
- PlaylistTableModel model = getModel();
int firstIndex = -1;
Iterator<File> 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;
/**
* シーケンスを削除するアクション
*/
- Action deleteSequenceAction = getModel().new SelectedSequenceAction(
+ Action deleteSequenceAction = new SelectedSequenceAction(
"Delete", MidiSequenceEditorDialog.deleteIcon,
"Delete selected MIDI sequence - 選択した曲をプレイリストから削除"
) {
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,
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,
/**
* ファイル保存アクション
*/
- 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));
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;
*/
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
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; }
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の場合、ファイル名なし)
sequenceModelList.add(new SequenceTrackListTableModel(this, sequence, filename));
int lastIndex = sequenceModelList.size() - 1;
fireTableRowsInserted(lastIndex, lastIndex);
- selectionModel.setSelectionInterval(lastIndex, lastIndex);
return lastIndex;
}
/**
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;
* @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<String>(){{
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 シーケンス(トラックリスト)データモデル
*/
else {
addTrackAction.setEnabled(true);
}
- selectionModel.clearSelection();
- selectionModel.removeListSelectionListener(selectionListener);
super.setModel(model);
- setSelectionModel(model.getSelectionModel());
- titleLabel.setSelection(model.getParent().getSelectionModel());
- selectionModel.addListSelectionListener(selectionListener);
}
/**
* 曲番号表示付きタイトルラベル
/**
* 曲番号表示付きタイトルラベル
*/
- 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();
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;
*/
private List<MidiEventTableModel> 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シーケンス
* @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;