import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
+import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JOptionPane;
import javax.swing.event.HyperlinkEvent;
}
@Override
public void actionPerformed(ActionEvent e) {
+ JComponent c = (JComponent)e.getSource();
JOptionPane.showMessageDialog(
- null, AboutMessagePane.this, getValue(NAME).toString(),
+ c.getRootPane(),
+ AboutMessagePane.this, getValue(NAME).toString(),
JOptionPane.INFORMATION_MESSAGE, imageIcon
);
}
return d.addToPlaylist();
}
/**
- * プレイリスト上で現在選択されているMIDIシーケンスを、
- * シーケンサへロードして再生します。
- * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
- * @throws IllegalStateException MIDIシーケンサデバイスが閉じている場合
+ * プレイリスト上で現在選択されているMIDIシーケンスをシーケンサへロードして再生します。
*/
- public void play() throws InvalidMidiDataException {
+ public void play() {
play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex());
}
/**
* 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスをシーケンサへロードして再生します。
* @param index インデックス値(0から始まる)
- * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
- * @throws IllegalStateException MIDIシーケンサデバイスが閉じている場合
*/
- public void play(int index) throws InvalidMidiDataException {
- playlistModel.play(index);
- }
+ public void play(int index) { midiEditor.play(index); }
/**
* シーケンサが実行中かどうかを返します。
* {@link Sequencer#isRunning()} の戻り値をそのまま返します。
*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20170417.1";
+ public static final String VERSION = "Ver.20170419.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/";
setTransferHandler(midiEditor.transferHandler);
//
// MIDIエディタのイベントダイアログを、ピアノ鍵盤のイベント送出ダイアログと共用
- keyboardPanel.setEventDialog(midiEditor.eventDialog);
+ keyboardPanel.setEventDialog(midiEditor.eventListTable.eventDialog);
//
// 歌詞表示/コード入力フィールド
(lyricDisplay = new ChordTextField(sequencerModel)).addActionListener(
SwingUtilities.invokeLater(()->new MidiChordHelper(fileList));
}
private static boolean confirmBeforeExit() {
- String message = "MIDI file not saved, exit anyway ?\n"+
+ String message = "MIDI file not saved - Really exit ?\n"+
"MIDIファイルが保存されていません。終了してよろしいですか?";
return JOptionPane.showConfirmDialog(
null, message, ChordHelperApplet.VersionInfo.NAME,
--- /dev/null
+package camidion.chordhelper.midieditor;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.MouseEvent;
+import java.util.Arrays;
+import java.util.EventObject;
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.ShortMessage;
+import javax.swing.AbstractAction;
+import javax.swing.AbstractCellEditor;
+import javax.swing.Action;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JToggleButton;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
+
+import camidion.chordhelper.ChordHelperApplet;
+import camidion.chordhelper.mididevice.VirtualMidiDevice;
+
+/**
+ * MIDIイベントリストテーブルビュー(選択中のトラックの中身)
+ */
+public class MidiEventTable extends JTable {
+ /**
+ * 操作音を鳴らすMIDI出力デバイス
+ */
+ private VirtualMidiDevice outputMidiDevice;
+ /**
+ * MIDIイベント入力ダイアログ(イベント入力とイベント送出で共用)
+ */
+ public MidiEventDialog eventDialog = new MidiEventDialog();
+ /**
+ * 新しいイベントリストテーブルを構築します。
+ * <p>データモデルとして一つのトラックのイベントリストを指定できます。
+ * トラックを切り替えたいときは {@link #setModel(TableModel)}
+ * でデータモデルを異なるトラックのものに切り替えます。
+ * </p>
+ *
+ * @param model トラック(イベントリスト)データモデル
+ * @param outputMidiDevice 操作音出力先MIDIデバイス
+ */
+ public MidiEventTable(TrackEventListTableModel model, VirtualMidiDevice outputMidiDevice) {
+ super(model, null, model.getSelectionModel());
+ this.outputMidiDevice = outputMidiDevice;
+ //
+ // 列モデルにセルエディタを設定
+ eventCellEditor = new MidiEventCellEditor();
+ setAutoCreateColumnsFromModel(false);
+ //
+ eventSelectionListener = new EventSelectionListener();
+ titleLabel = new TitleLabel();
+ //
+ TableColumnModel cm = getColumnModel();
+ Arrays.stream(TrackEventListTableModel.Column.values()).forEach(c->
+ cm.getColumn(c.ordinal()).setPreferredWidth(c.preferredWidth)
+ );
+ }
+ /**
+ * このテーブルビューが表示するデータを提供する
+ * トラック(イベントリスト)データモデルを返します。
+ * @return トラック(イベントリスト)データモデル
+ */
+ @Override
+ public TrackEventListTableModel getModel() {
+ return (TrackEventListTableModel) super.getModel();
+ }
+ public void updateTo(SequenceTrackListTableModel sequenceModel) {
+ titleLabel.updateTrackNumber(sequenceModel.getSelectionModel().getMinSelectionIndex());
+ TrackEventListTableModel oldTrackModel = getModel();
+ TrackEventListTableModel newTrackModel = sequenceModel.getSelectedTrackModel();
+ if( oldTrackModel == newTrackModel )
+ return;
+ if( newTrackModel == null ) {
+ newTrackModel = getModel().getParent().getParent().emptyEventListTableModel;
+ queryJumpEventAction.setEnabled(false);
+ queryAddEventAction.setEnabled(false);
+
+ queryPasteEventAction.setEnabled(false);
+ copyEventAction.setEnabled(false);
+ deleteEventAction.setEnabled(false);
+ cutEventAction.setEnabled(false);
+ }
+ else {
+ queryJumpEventAction.setEnabled(true);
+ queryAddEventAction.setEnabled(true);
+ }
+ oldTrackModel.getSelectionModel().removeListSelectionListener(eventSelectionListener);
+ setModel(newTrackModel);
+ setSelectionModel(newTrackModel.getSelectionModel());
+ newTrackModel.getSelectionModel().addListSelectionListener(eventSelectionListener);
+ }
+ /**
+ * タイトルラベル
+ */
+ TitleLabel titleLabel;
+ /**
+ * 親テーブルの選択トラックの変更に反応する
+ * トラック番号つきタイトルラベル
+ */
+ private class TitleLabel extends JLabel {
+ private static final String TITLE = "MIDI Events";
+ private TitleLabel() { super(TITLE); }
+ private void updateTrackNumber(int index) {
+ String text = TITLE;
+ if( index >= 0 ) text = String.format(TITLE+" - track #%d", index);
+ setText(text);
+ }
+ }
+
+ /**
+ * イベント選択リスナー
+ */
+ private EventSelectionListener eventSelectionListener;
+ /**
+ * 選択イベントの変更に反応するリスナー
+ */
+ private class EventSelectionListener implements ListSelectionListener {
+ public EventSelectionListener() {
+ getModel().getSelectionModel().addListSelectionListener(this);
+ }
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if( e.getValueIsAdjusting() )
+ return;
+ if( getSelectionModel().isSelectionEmpty() ) {
+ queryPasteEventAction.setEnabled(false);
+ copyEventAction.setEnabled(false);
+ deleteEventAction.setEnabled(false);
+ cutEventAction.setEnabled(false);
+ }
+ else {
+ copyEventAction.setEnabled(true);
+ deleteEventAction.setEnabled(true);
+ cutEventAction.setEnabled(true);
+ TrackEventListTableModel trackModel = getModel();
+ int minIndex = getSelectionModel().getMinSelectionIndex();
+ MidiEvent midiEvent = trackModel.getMidiEvent(minIndex);
+ if( midiEvent != null ) {
+ MidiMessage msg = midiEvent.getMessage();
+ if( msg instanceof ShortMessage ) {
+ ShortMessage sm = (ShortMessage)msg;
+ int cmd = sm.getCommand();
+ if( cmd == 0x80 || cmd == 0x90 || cmd == 0xA0 ) {
+ // ノート番号を持つ場合、音を鳴らす。
+ MidiChannel outMidiChannels[] = outputMidiDevice.getChannels();
+ int ch = sm.getChannel();
+ int note = sm.getData1();
+ int vel = sm.getData2();
+ outMidiChannels[ch].noteOn(note, vel);
+ outMidiChannels[ch].noteOff(note, vel);
+ }
+ }
+ }
+ if( pairNoteOnOffModel.isSelected() ) {
+ int maxIndex = getSelectionModel().getMaxSelectionIndex();
+ int partnerIndex;
+ for( int i=minIndex; i<=maxIndex; i++ ) {
+ if( ! getSelectionModel().isSelectedIndex(i) ) continue;
+ partnerIndex = trackModel.getIndexOfPartnerFor(i);
+ if( partnerIndex >= 0 && ! getSelectionModel().isSelectedIndex(partnerIndex) )
+ getSelectionModel().addSelectionInterval(partnerIndex, partnerIndex);
+ }
+ }
+ }
+ }
+ }
+ /**
+ * Pair noteON/OFF トグルボタンモデル
+ */
+ JToggleButton.ToggleButtonModel
+ pairNoteOnOffModel = new JToggleButton.ToggleButtonModel() {
+ {
+ addItemListener(e->eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()));
+ setSelected(true);
+ }
+ };
+ private class EventEditContext {
+ /**
+ * 編集対象トラック
+ */
+ private TrackEventListTableModel trackModel;
+ /**
+ * tick位置入力モデル
+ */
+ private TickPositionModel tickPositionModel = new TickPositionModel();
+ /**
+ * 選択されたイベント
+ */
+ private MidiEvent selectedMidiEvent = null;
+ /**
+ * 選択されたイベントの場所
+ */
+ private int selectedIndex = -1;
+ /**
+ * 選択されたイベントのtick位置
+ */
+ private long currentTick = 0;
+ /**
+ * 上書きして削除対象にする変更前イベント(null可)
+ */
+ private MidiEvent[] midiEventsToBeOverwritten;
+ /**
+ * 選択したイベントを入力ダイアログなどに反映します。
+ * @param model 対象データモデル
+ */
+ private void setSelectedEvent(TrackEventListTableModel trackModel) {
+ this.trackModel = trackModel;
+ SequenceTrackListTableModel sequenceTableModel = trackModel.getParent();
+ int ppq = sequenceTableModel.getSequence().getResolution();
+ eventDialog.midiMessageForm.durationForm.setPPQ(ppq);
+ tickPositionModel.setSequenceIndex(sequenceTableModel.getSequenceTickIndex());
+
+ selectedIndex = trackModel.getSelectionModel().getMinSelectionIndex();
+ selectedMidiEvent = selectedIndex < 0 ? null : trackModel.getMidiEvent(selectedIndex);
+ currentTick = selectedMidiEvent == null ? 0 : selectedMidiEvent.getTick();
+ tickPositionModel.setTickPosition(currentTick);
+ }
+ public void setupForEdit(TrackEventListTableModel trackModel) {
+ MidiEvent partnerEvent = null;
+ eventDialog.midiMessageForm.setMessage(
+ selectedMidiEvent.getMessage(),
+ trackModel.getParent().charset
+ );
+ if( eventDialog.midiMessageForm.isNote() ) {
+ int partnerIndex = trackModel.getIndexOfPartnerFor(selectedIndex);
+ if( partnerIndex < 0 ) {
+ eventDialog.midiMessageForm.durationForm.setDuration(0);
+ }
+ else {
+ partnerEvent = trackModel.getMidiEvent(partnerIndex);
+ long partnerTick = partnerEvent.getTick();
+ long duration = currentTick > partnerTick ?
+ currentTick - partnerTick : partnerTick - currentTick ;
+ eventDialog.midiMessageForm.durationForm.setDuration((int)duration);
+ }
+ }
+ if(partnerEvent == null)
+ midiEventsToBeOverwritten = new MidiEvent[] {selectedMidiEvent};
+ else
+ midiEventsToBeOverwritten = new MidiEvent[] {selectedMidiEvent, partnerEvent};
+ }
+ private Action jumpEventAction = new AbstractAction() {
+ { putValue(NAME,"Jump"); }
+ public void actionPerformed(ActionEvent e) {
+ long tick = tickPositionModel.getTickPosition();
+ scrollToEventAt(tick);
+ eventDialog.setVisible(false);
+ trackModel = null;
+ }
+ };
+ private Action pasteEventAction = new AbstractAction() {
+ { putValue(NAME,"Paste"); }
+ public void actionPerformed(ActionEvent e) {
+ long tick = tickPositionModel.getTickPosition();
+ clipBoard.paste(trackModel, tick);
+ scrollToEventAt(tick);
+ // ペーストされたので変更フラグを立てる(曲の長さが変わるが、それも自動的にプレイリストに通知される)
+ SequenceTrackListTableModel seqModel = trackModel.getParent();
+ seqModel.setModified(true);
+ eventDialog.setVisible(false);
+ trackModel = null;
+ }
+ };
+ private boolean applyEvent() {
+ long tick = tickPositionModel.getTickPosition();
+ MidiMessageForm form = eventDialog.midiMessageForm;
+ SequenceTrackListTableModel seqModel = trackModel.getParent();
+ MidiMessage msg = form.getMessage(seqModel.charset);
+ if( msg == null ) {
+ return false;
+ }
+ MidiEvent newMidiEvent = new MidiEvent(msg, tick);
+ if( midiEventsToBeOverwritten != null ) {
+ // 上書き消去するための選択済イベントがあった場合
+ trackModel.removeMidiEvents(midiEventsToBeOverwritten);
+ }
+ if( ! trackModel.addMidiEvent(newMidiEvent) ) {
+ System.out.println("addMidiEvent failure");
+ return false;
+ }
+ if(pairNoteOnOffModel.isSelected() && form.isNote()) {
+ ShortMessage sm = form.createPartnerMessage();
+ if(sm == null)
+ scrollToEventAt( tick );
+ else {
+ int duration = form.durationForm.getDuration();
+ if( form.isNote(false) ) {
+ duration = -duration;
+ }
+ long partnerTick = tick + (long)duration;
+ if( partnerTick < 0L ) partnerTick = 0L;
+ MidiEvent partner = new MidiEvent((MidiMessage)sm, partnerTick);
+ if( ! trackModel.addMidiEvent(partner) ) {
+ System.out.println("addMidiEvent failure (note on/off partner message)");
+ }
+ scrollToEventAt(partnerTick > tick ? partnerTick : tick);
+ }
+ }
+ seqModel.setModified(true);
+ eventDialog.setVisible(false);
+ return true;
+ }
+ }
+ private EventEditContext editContext = new EventEditContext();
+ /**
+ * 指定のTick位置へジャンプするアクション
+ */
+ Action queryJumpEventAction = new AbstractAction() {
+ {
+ putValue(NAME,"Jump to ...");
+ setEnabled(false);
+ }
+ public void actionPerformed(ActionEvent e) {
+ editContext.setSelectedEvent(getModel());
+ eventDialog.openTickForm("Jump selection to", editContext.jumpEventAction);
+ }
+ };
+ /**
+ * 新しいイベントの追加を行うアクション
+ */
+ Action queryAddEventAction = new AbstractAction() {
+ {
+ putValue(NAME,"New");
+ setEnabled(false);
+ }
+ public void actionPerformed(ActionEvent e) {
+ TrackEventListTableModel model = getModel();
+ editContext.setSelectedEvent(model);
+ editContext.midiEventsToBeOverwritten = null;
+ eventDialog.openEventForm("New MIDI event", eventCellEditor.applyEventAction, model.getChannel());
+ }
+ };
+ /**
+ * MIDIイベントのコピー&ペーストを行うためのクリップボード
+ */
+ private class LocalClipBoard {
+ private MidiEvent copiedEventsToPaste[];
+ private int copiedEventsPPQ = 0;
+ public void copy(TrackEventListTableModel model, boolean withRemove) {
+ copiedEventsToPaste = model.getSelectedMidiEvents();
+ copiedEventsPPQ = model.getParent().getSequence().getResolution();
+ if( withRemove ) model.removeMidiEvents(copiedEventsToPaste);
+ boolean en = (copiedEventsToPaste != null && copiedEventsToPaste.length > 0);
+ queryPasteEventAction.setEnabled(en);
+ }
+ public void cut(TrackEventListTableModel model) {copy(model,true);}
+ public void copy(TrackEventListTableModel model){copy(model,false);}
+ public void paste(TrackEventListTableModel model, long tick) {
+ model.addMidiEvents(copiedEventsToPaste, tick, copiedEventsPPQ);
+ }
+ }
+ private LocalClipBoard clipBoard = new LocalClipBoard();
+ /**
+ * 指定のTick位置へ貼り付けるアクション
+ */
+ Action queryPasteEventAction = new AbstractAction() {
+ {
+ putValue(NAME,"Paste to ...");
+ setEnabled(false);
+ }
+ public void actionPerformed(ActionEvent e) {
+ editContext.setSelectedEvent(getModel());
+ eventDialog.openTickForm("Paste to", editContext.pasteEventAction);
+ }
+ };
+ /**
+ * イベントカットアクション
+ */
+ public Action cutEventAction = new AbstractAction("Cut") {
+ private static final String CONFIRM_MESSAGE =
+ "Do you want to cut selected event ?\n選択したMIDIイベントを切り取りますか?";
+ { setEnabled(false); }
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if( JOptionPane.showConfirmDialog(
+ ((JComponent)event.getSource()).getRootPane(),
+ CONFIRM_MESSAGE,
+ ChordHelperApplet.VersionInfo.NAME,
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION
+ ) clipBoard.cut(getModel());
+ }
+ };
+ /**
+ * イベントコピーアクション
+ */
+ public Action copyEventAction = new AbstractAction("Copy") {
+ { setEnabled(false); }
+ @Override
+ public void actionPerformed(ActionEvent e) { clipBoard.copy(getModel()); }
+ };
+ /**
+ * イベント削除アクション
+ */
+ public Action deleteEventAction = new AbstractAction("Delete", MidiSequenceEditorDialog.deleteIcon) {
+ private static final String CONFIRM_MESSAGE =
+ "Do you want to delete selected event ?\n選択したMIDIイベントを削除しますか?";
+ { setEnabled(false); }
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if( JOptionPane.showConfirmDialog(
+ ((JComponent)event.getSource()).getRootPane(),
+ CONFIRM_MESSAGE,
+ ChordHelperApplet.VersionInfo.NAME,
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION
+ ) getModel().removeSelectedMidiEvents();
+ }
+ };
+ /**
+ * MIDIイベント表のセルエディタ
+ */
+ private MidiEventCellEditor eventCellEditor;
+ /**
+ * MIDIイベント表のセルエディタ
+ */
+ class MidiEventCellEditor extends AbstractCellEditor implements TableCellEditor {
+ /**
+ * MIDIイベントセルエディタを構築します。
+ */
+ public MidiEventCellEditor() {
+ eventDialog.midiMessageForm.setOutputMidiChannels(outputMidiDevice.getChannels());
+ eventDialog.tickPositionInputForm.setModel(editContext.tickPositionModel);
+ int index = TrackEventListTableModel.Column.MESSAGE.ordinal();
+ getColumnModel().getColumn(index).setCellEditor(this);
+ }
+ /**
+ * セルをダブルクリックしないと編集できないようにします。
+ * @param e イベント(マウスイベント)
+ * @return 編集可能になったらtrue
+ */
+ @Override
+ public boolean isCellEditable(EventObject e) {
+ return (e instanceof MouseEvent) ?
+ ((MouseEvent)e).getClickCount() == 2 : super.isCellEditable(e);
+ }
+ @Override
+ public Object getCellEditorValue() { return null; }
+ /**
+ * MIDIメッセージダイアログが閉じたときにセル編集を中止するリスナー
+ */
+ private ComponentListener dialogComponentListener = new ComponentAdapter() {
+ @Override
+ public void componentHidden(ComponentEvent e) {
+ fireEditingCanceled();
+ // 用が済んだら当リスナーを除去
+ eventDialog.removeComponentListener(this);
+ }
+ };
+ /**
+ * 既存イベントを編集するアクション
+ */
+ private Action editEventAction = new AbstractAction() {
+ public void actionPerformed(ActionEvent e) {
+ TrackEventListTableModel model = getModel();
+ editContext.setSelectedEvent(model);
+ if( editContext.selectedMidiEvent == null )
+ return;
+ editContext.setupForEdit(model);
+ eventDialog.addComponentListener(dialogComponentListener);
+ eventDialog.openEventForm("Change MIDI event", applyEventAction);
+ }
+ };
+ /**
+ * イベント編集ボタン
+ */
+ private JButton editEventButton = new JButton(editEventAction){{
+ setHorizontalAlignment(JButton.LEFT);
+ }};
+ @Override
+ public Component getTableCellEditorComponent(
+ JTable table, Object value, boolean isSelected, int row, int column
+ ) {
+ editEventButton.setText(value.toString());
+ return editEventButton;
+ }
+ /**
+ * 入力したイベントを反映するアクション
+ */
+ private Action applyEventAction = new AbstractAction() {
+ { putValue(NAME,"OK"); }
+ public void actionPerformed(ActionEvent e) {
+ if( editContext.applyEvent() ) fireEditingStopped();
+ }
+ };
+ }
+ /**
+ * スクロール可能なMIDIイベントテーブルビュー
+ */
+ JScrollPane scrollPane = new JScrollPane(this);
+ /**
+ * 指定の MIDI tick のイベントへスクロールします。
+ * @param tick MIDI tick
+ */
+ public void scrollToEventAt(long tick) {
+ int index = getModel().tickToIndex(tick);
+ scrollPane.getVerticalScrollBar().setValue(index * getRowHeight());
+ getSelectionModel().setSelectionInterval(index, index);
+ }
+}
\ No newline at end of file
package camidion.chordhelper.midieditor;
-import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.ActionEvent;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
-import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Arrays;
-import java.util.EventObject;
import java.util.List;
-import javax.sound.midi.MidiChannel;
-import javax.sound.midi.MidiEvent;
-import javax.sound.midi.MidiMessage;
import javax.sound.midi.Sequencer;
-import javax.sound.midi.ShortMessage;
import javax.swing.AbstractAction;
-import javax.swing.AbstractCellEditor;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
+import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
-import javax.swing.JToggleButton;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.border.EtchedBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumnModel;
-import javax.swing.table.TableModel;
import camidion.chordhelper.ButtonIcon;
import camidion.chordhelper.ChordHelperApplet;
/**
* このダイアログを開きます。表示されていなければ表示し、すでに表示されていたら最前面に移動します。
*/
- public void open() {
- if( isVisible() ) toFront(); else setVisible(true);
- }
+ public void open() { if( isVisible() ) toFront(); else setVisible(true); }
/**
* このダイアログを表示するボタン用アクション
*/
*/
public void play(int index) {
try {
- PlaylistTableModel playlist = sequenceListTable.getModel();
+ PlaylistTableModel playlist = getPlaylistModel();
MidiSequencerModel sequencerModel = playlist.getSequencerModel();
if( sequencerModel.getSequencer().isRunning() ) { open(); return; }
if( index >= 0 ) playlist.play(index);
/**
* プレイリストビュー(シーケンスリスト)
*/
- public SequenceListTable sequenceListTable;
+ public PlaylistTable sequenceListTable;
/**
* MIDIトラックリストテーブルビュー(選択中のシーケンスの中身)
*/
- private TrackListTable trackListTable;
+ private SequenceTrackListTable trackListTable;
/**
* MIDIイベントリストテーブルビュー(選択中のトラックの中身)
*/
- private EventListTable eventListTable;
- /**
- * MIDIイベント入力ダイアログ(イベント入力とイベント送出で共用)
- */
- public MidiEventDialog eventDialog = new MidiEventDialog();
- /**
- * 操作音を鳴らすMIDI出力デバイス
- */
- private VirtualMidiDevice outputMidiDevice;
+ public MidiEventTable eventListTable;
/**
* シーケンス(トラックリスト)テーブルビュー
*/
- public class TrackListTable extends JTable {
+ public class SequenceTrackListTable extends JTable {
/**
* トラックリストテーブルビューを構築します。
* @param model シーケンス(トラックリスト)データモデル
*/
- public TrackListTable(SequenceTrackListTableModel model) {
+ public SequenceTrackListTable(SequenceTrackListTableModel model) {
super(model, null, model.getSelectionModel());
//
// 録音対象のMIDIチャンネルをコンボボックスで選択できるようにする
*/
@Override
public SequenceTrackListTableModel getModel() {
- return (SequenceTrackListTableModel) super.getModel();
+ return (SequenceTrackListTableModel)dataModel;
}
/**
* タイトルラベル
@Override
public void valueChanged(ListSelectionEvent e) {
if( e != null && e.getValueIsAdjusting() ) return;
- ListSelectionModel tlsm = getModel().getSelectionModel();
- deleteTrackAction.setEnabled(! tlsm.isSelectionEmpty());
- eventListTable.titleLabel.update(tlsm, getModel());
+ ListSelectionModel selModel = getModel().getSelectionModel();
+ deleteTrackAction.setEnabled(! selModel.isSelectionEmpty());
+ eventListTable.updateTo(getModel());
}
};
/**
setEnabled(false);
}
@Override
- public void actionPerformed(ActionEvent e) {
+ public void actionPerformed(ActionEvent event) {
if( JOptionPane.showConfirmDialog(
- TrackListTable.this.getRootPane(),
+ ((JComponent)event.getSource()).getRootPane(),
CONFIRM_MESSAGE,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.YES_NO_OPTION,
}
/**
- * MIDIイベントリストテーブルビュー(選択中のトラックの中身)
- */
- public class EventListTable extends JTable {
- /**
- * 新しいイベントリストテーブルを構築します。
- * <p>データモデルとして一つのトラックのイベントリストを指定できます。
- * トラックを切り替えたいときは {@link #setModel(TableModel)}
- * でデータモデルを異なるトラックのものに切り替えます。
- * </p>
- *
- * @param model トラック(イベントリスト)データモデル
- */
- public EventListTable(TrackEventListTableModel model) {
- super(model, null, model.getSelectionModel());
- //
- // 列モデルにセルエディタを設定
- eventCellEditor = new MidiEventCellEditor();
- setAutoCreateColumnsFromModel(false);
- //
- eventSelectionListener = new EventSelectionListener();
- titleLabel = new TitleLabel();
- //
- TableColumnModel cm = getColumnModel();
- Arrays.stream(TrackEventListTableModel.Column.values()).forEach(c->
- cm.getColumn(c.ordinal()).setPreferredWidth(c.preferredWidth)
- );
- }
- /**
- * このテーブルビューが表示するデータを提供する
- * トラック(イベントリスト)データモデルを返します。
- * @return トラック(イベントリスト)データモデル
- */
- @Override
- public TrackEventListTableModel getModel() {
- return (TrackEventListTableModel) super.getModel();
- }
- /**
- * タイトルラベル
- */
- TitleLabel titleLabel;
- /**
- * 親テーブルの選択トラックの変更に反応する
- * トラック番号つきタイトルラベル
- */
- private class TitleLabel extends JLabel {
- private static final String TITLE = "MIDI Events";
- public TitleLabel() { super(TITLE); }
- public void update(ListSelectionModel tlsm, SequenceTrackListTableModel sequenceModel) {
- String text = TITLE;
- TrackEventListTableModel oldTrackModel = getModel();
- int index = tlsm.getMinSelectionIndex();
- if( index >= 0 ) {
- text = String.format(TITLE+" - track #%d", index);
- }
- setText(text);
- TrackEventListTableModel newTrackModel = sequenceModel.getSelectedTrackModel();
- if( oldTrackModel == newTrackModel )
- return;
- if( newTrackModel == null ) {
- newTrackModel = getModel().getParent().getParent().emptyEventListTableModel;
- queryJumpEventAction.setEnabled(false);
- queryAddEventAction.setEnabled(false);
-
- queryPasteEventAction.setEnabled(false);
- copyEventAction.setEnabled(false);
- deleteEventAction.setEnabled(false);
- cutEventAction.setEnabled(false);
- }
- else {
- queryJumpEventAction.setEnabled(true);
- queryAddEventAction.setEnabled(true);
- }
- oldTrackModel.getSelectionModel().removeListSelectionListener(eventSelectionListener);
- setModel(newTrackModel);
- setSelectionModel(newTrackModel.getSelectionModel());
- newTrackModel.getSelectionModel().addListSelectionListener(eventSelectionListener);
- }
- }
-
- /**
- * イベント選択リスナー
- */
- private EventSelectionListener eventSelectionListener;
- /**
- * 選択イベントの変更に反応するリスナー
- */
- private class EventSelectionListener implements ListSelectionListener {
- public EventSelectionListener() {
- getModel().getSelectionModel().addListSelectionListener(this);
- }
- @Override
- public void valueChanged(ListSelectionEvent e) {
- if( e.getValueIsAdjusting() )
- return;
- if( getSelectionModel().isSelectionEmpty() ) {
- queryPasteEventAction.setEnabled(false);
- copyEventAction.setEnabled(false);
- deleteEventAction.setEnabled(false);
- cutEventAction.setEnabled(false);
- }
- else {
- copyEventAction.setEnabled(true);
- deleteEventAction.setEnabled(true);
- cutEventAction.setEnabled(true);
- TrackEventListTableModel trackModel = getModel();
- int minIndex = getSelectionModel().getMinSelectionIndex();
- MidiEvent midiEvent = trackModel.getMidiEvent(minIndex);
- if( midiEvent != null ) {
- MidiMessage msg = midiEvent.getMessage();
- if( msg instanceof ShortMessage ) {
- ShortMessage sm = (ShortMessage)msg;
- int cmd = sm.getCommand();
- if( cmd == 0x80 || cmd == 0x90 || cmd == 0xA0 ) {
- // ノート番号を持つ場合、音を鳴らす。
- MidiChannel outMidiChannels[] = outputMidiDevice.getChannels();
- int ch = sm.getChannel();
- int note = sm.getData1();
- int vel = sm.getData2();
- outMidiChannels[ch].noteOn(note, vel);
- outMidiChannels[ch].noteOff(note, vel);
- }
- }
- }
- if( pairNoteOnOffModel.isSelected() ) {
- int maxIndex = getSelectionModel().getMaxSelectionIndex();
- int partnerIndex;
- for( int i=minIndex; i<=maxIndex; i++ ) {
- if( ! getSelectionModel().isSelectedIndex(i) ) continue;
- partnerIndex = trackModel.getIndexOfPartnerFor(i);
- if( partnerIndex >= 0 && ! getSelectionModel().isSelectedIndex(partnerIndex) )
- getSelectionModel().addSelectionInterval(partnerIndex, partnerIndex);
- }
- }
- }
- }
- }
- /**
- * Pair noteON/OFF トグルボタンモデル
- */
- private JToggleButton.ToggleButtonModel
- pairNoteOnOffModel = new JToggleButton.ToggleButtonModel() {
- {
- addItemListener(e->eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()));
- setSelected(true);
- }
- };
- private class EventEditContext {
- /**
- * 編集対象トラック
- */
- private TrackEventListTableModel trackModel;
- /**
- * tick位置入力モデル
- */
- private TickPositionModel tickPositionModel = new TickPositionModel();
- /**
- * 選択されたイベント
- */
- private MidiEvent selectedMidiEvent = null;
- /**
- * 選択されたイベントの場所
- */
- private int selectedIndex = -1;
- /**
- * 選択されたイベントのtick位置
- */
- private long currentTick = 0;
- /**
- * 上書きして削除対象にする変更前イベント(null可)
- */
- private MidiEvent[] midiEventsToBeOverwritten;
- /**
- * 選択したイベントを入力ダイアログなどに反映します。
- * @param model 対象データモデル
- */
- private void setSelectedEvent(TrackEventListTableModel trackModel) {
- this.trackModel = trackModel;
- SequenceTrackListTableModel sequenceTableModel = trackModel.getParent();
- int ppq = sequenceTableModel.getSequence().getResolution();
- eventDialog.midiMessageForm.durationForm.setPPQ(ppq);
- tickPositionModel.setSequenceIndex(sequenceTableModel.getSequenceTickIndex());
-
- selectedIndex = trackModel.getSelectionModel().getMinSelectionIndex();
- selectedMidiEvent = selectedIndex < 0 ? null : trackModel.getMidiEvent(selectedIndex);
- currentTick = selectedMidiEvent == null ? 0 : selectedMidiEvent.getTick();
- tickPositionModel.setTickPosition(currentTick);
- }
- public void setupForEdit(TrackEventListTableModel trackModel) {
- MidiEvent partnerEvent = null;
- eventDialog.midiMessageForm.setMessage(
- selectedMidiEvent.getMessage(),
- trackModel.getParent().charset
- );
- if( eventDialog.midiMessageForm.isNote() ) {
- int partnerIndex = trackModel.getIndexOfPartnerFor(selectedIndex);
- if( partnerIndex < 0 ) {
- eventDialog.midiMessageForm.durationForm.setDuration(0);
- }
- else {
- partnerEvent = trackModel.getMidiEvent(partnerIndex);
- long partnerTick = partnerEvent.getTick();
- long duration = currentTick > partnerTick ?
- currentTick - partnerTick : partnerTick - currentTick ;
- eventDialog.midiMessageForm.durationForm.setDuration((int)duration);
- }
- }
- if(partnerEvent == null)
- midiEventsToBeOverwritten = new MidiEvent[] {selectedMidiEvent};
- else
- midiEventsToBeOverwritten = new MidiEvent[] {selectedMidiEvent, partnerEvent};
- }
- private Action jumpEventAction = new AbstractAction() {
- { putValue(NAME,"Jump"); }
- public void actionPerformed(ActionEvent e) {
- long tick = tickPositionModel.getTickPosition();
- scrollToEventAt(tick);
- eventDialog.setVisible(false);
- trackModel = null;
- }
- };
- private Action pasteEventAction = new AbstractAction() {
- { putValue(NAME,"Paste"); }
- public void actionPerformed(ActionEvent e) {
- long tick = tickPositionModel.getTickPosition();
- clipBoard.paste(trackModel, tick);
- scrollToEventAt(tick);
- // ペーストされたので変更フラグを立てる(曲の長さが変わるが、それも自動的にプレイリストに通知される)
- SequenceTrackListTableModel seqModel = trackModel.getParent();
- seqModel.setModified(true);
- eventDialog.setVisible(false);
- trackModel = null;
- }
- };
- private boolean applyEvent() {
- long tick = tickPositionModel.getTickPosition();
- MidiMessageForm form = eventDialog.midiMessageForm;
- SequenceTrackListTableModel seqModel = trackModel.getParent();
- MidiMessage msg = form.getMessage(seqModel.charset);
- if( msg == null ) {
- return false;
- }
- MidiEvent newMidiEvent = new MidiEvent(msg, tick);
- if( midiEventsToBeOverwritten != null ) {
- // 上書き消去するための選択済イベントがあった場合
- trackModel.removeMidiEvents(midiEventsToBeOverwritten);
- }
- if( ! trackModel.addMidiEvent(newMidiEvent) ) {
- System.out.println("addMidiEvent failure");
- return false;
- }
- if(pairNoteOnOffModel.isSelected() && form.isNote()) {
- ShortMessage sm = form.createPartnerMessage();
- if(sm == null)
- scrollToEventAt( tick );
- else {
- int duration = form.durationForm.getDuration();
- if( form.isNote(false) ) {
- duration = -duration;
- }
- long partnerTick = tick + (long)duration;
- if( partnerTick < 0L ) partnerTick = 0L;
- MidiEvent partner = new MidiEvent((MidiMessage)sm, partnerTick);
- if( ! trackModel.addMidiEvent(partner) ) {
- System.out.println("addMidiEvent failure (note on/off partner message)");
- }
- scrollToEventAt(partnerTick > tick ? partnerTick : tick);
- }
- }
- seqModel.setModified(true);
- eventDialog.setVisible(false);
- return true;
- }
- }
- private EventEditContext editContext = new EventEditContext();
- /**
- * 指定のTick位置へジャンプするアクション
- */
- Action queryJumpEventAction = new AbstractAction() {
- {
- putValue(NAME,"Jump to ...");
- setEnabled(false);
- }
- public void actionPerformed(ActionEvent e) {
- editContext.setSelectedEvent(getModel());
- eventDialog.openTickForm("Jump selection to", editContext.jumpEventAction);
- }
- };
- /**
- * 新しいイベントの追加を行うアクション
- */
- Action queryAddEventAction = new AbstractAction() {
- {
- putValue(NAME,"New");
- setEnabled(false);
- }
- public void actionPerformed(ActionEvent e) {
- TrackEventListTableModel model = getModel();
- editContext.setSelectedEvent(model);
- editContext.midiEventsToBeOverwritten = null;
- eventDialog.openEventForm("New MIDI event", eventCellEditor.applyEventAction, model.getChannel());
- }
- };
- /**
- * MIDIイベントのコピー&ペーストを行うためのクリップボード
- */
- private class LocalClipBoard {
- private MidiEvent copiedEventsToPaste[];
- private int copiedEventsPPQ = 0;
- public void copy(TrackEventListTableModel model, boolean withRemove) {
- copiedEventsToPaste = model.getSelectedMidiEvents();
- copiedEventsPPQ = model.getParent().getSequence().getResolution();
- if( withRemove ) model.removeMidiEvents(copiedEventsToPaste);
- boolean en = (copiedEventsToPaste != null && copiedEventsToPaste.length > 0);
- queryPasteEventAction.setEnabled(en);
- }
- public void cut(TrackEventListTableModel model) {copy(model,true);}
- public void copy(TrackEventListTableModel model){copy(model,false);}
- public void paste(TrackEventListTableModel model, long tick) {
- model.addMidiEvents(copiedEventsToPaste, tick, copiedEventsPPQ);
- }
- }
- private LocalClipBoard clipBoard = new LocalClipBoard();
- /**
- * 指定のTick位置へ貼り付けるアクション
- */
- Action queryPasteEventAction = new AbstractAction() {
- {
- putValue(NAME,"Paste to ...");
- setEnabled(false);
- }
- public void actionPerformed(ActionEvent e) {
- editContext.setSelectedEvent(getModel());
- eventDialog.openTickForm("Paste to", editContext.pasteEventAction);
- }
- };
- /**
- * イベントカットアクション
- */
- public Action cutEventAction = new AbstractAction("Cut") {
- private static final String CONFIRM_MESSAGE =
- "Do you want to cut selected event ?\n選択したMIDIイベントを切り取りますか?";
- { setEnabled(false); }
- @Override
- public void actionPerformed(ActionEvent e) {
- if( JOptionPane.showConfirmDialog(
- EventListTable.this.getRootPane(),
- CONFIRM_MESSAGE,
- ChordHelperApplet.VersionInfo.NAME,
- JOptionPane.YES_NO_OPTION,
- JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION
- ) clipBoard.cut(getModel());
- }
- };
- /**
- * イベントコピーアクション
- */
- public Action copyEventAction = new AbstractAction("Copy") {
- { setEnabled(false); }
- @Override
- public void actionPerformed(ActionEvent e) { clipBoard.copy(getModel()); }
- };
- /**
- * イベント削除アクション
- */
- public Action deleteEventAction = new AbstractAction("Delete", deleteIcon) {
- private static final String CONFIRM_MESSAGE =
- "Do you want to delete selected event ?\n選択したMIDIイベントを削除しますか?";
- { setEnabled(false); }
- @Override
- public void actionPerformed(ActionEvent e) {
- if( JOptionPane.showConfirmDialog(
- EventListTable.this.getRootPane(),
- CONFIRM_MESSAGE,
- ChordHelperApplet.VersionInfo.NAME,
- JOptionPane.YES_NO_OPTION,
- JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION
- ) getModel().removeSelectedMidiEvents();
- }
- };
- /**
- * MIDIイベント表のセルエディタ
- */
- private MidiEventCellEditor eventCellEditor;
- /**
- * MIDIイベント表のセルエディタ
- */
- class MidiEventCellEditor extends AbstractCellEditor implements TableCellEditor {
- /**
- * MIDIイベントセルエディタを構築します。
- */
- public MidiEventCellEditor() {
- eventDialog.midiMessageForm.setOutputMidiChannels(outputMidiDevice.getChannels());
- eventDialog.tickPositionInputForm.setModel(editContext.tickPositionModel);
- int index = TrackEventListTableModel.Column.MESSAGE.ordinal();
- getColumnModel().getColumn(index).setCellEditor(this);
- }
- /**
- * セルをダブルクリックしないと編集できないようにします。
- * @param e イベント(マウスイベント)
- * @return 編集可能になったらtrue
- */
- @Override
- public boolean isCellEditable(EventObject e) {
- return (e instanceof MouseEvent) ?
- ((MouseEvent)e).getClickCount() == 2 : super.isCellEditable(e);
- }
- @Override
- public Object getCellEditorValue() { return null; }
- /**
- * MIDIメッセージダイアログが閉じたときにセル編集を中止するリスナー
- */
- private ComponentListener dialogComponentListener = new ComponentAdapter() {
- @Override
- public void componentHidden(ComponentEvent e) {
- fireEditingCanceled();
- // 用が済んだら当リスナーを除去
- eventDialog.removeComponentListener(this);
- }
- };
- /**
- * 既存イベントを編集するアクション
- */
- private Action editEventAction = new AbstractAction() {
- public void actionPerformed(ActionEvent e) {
- TrackEventListTableModel model = getModel();
- editContext.setSelectedEvent(model);
- if( editContext.selectedMidiEvent == null )
- return;
- editContext.setupForEdit(model);
- eventDialog.addComponentListener(dialogComponentListener);
- eventDialog.openEventForm("Change MIDI event", applyEventAction);
- }
- };
- /**
- * イベント編集ボタン
- */
- private JButton editEventButton = new JButton(editEventAction){{
- setHorizontalAlignment(JButton.LEFT);
- }};
- @Override
- public Component getTableCellEditorComponent(
- JTable table, Object value, boolean isSelected, int row, int column
- ) {
- editEventButton.setText(value.toString());
- return editEventButton;
- }
- /**
- * 入力したイベントを反映するアクション
- */
- private Action applyEventAction = new AbstractAction() {
- { putValue(NAME,"OK"); }
- public void actionPerformed(ActionEvent e) {
- if( editContext.applyEvent() ) fireEditingStopped();
- }
- };
- }
- /**
- * スクロール可能なMIDIイベントテーブルビュー
- */
- private JScrollPane scrollPane = new JScrollPane(this);
- /**
- * 指定の MIDI tick のイベントへスクロールします。
- * @param tick MIDI tick
- */
- public void scrollToEventAt(long tick) {
- int index = getModel().tickToIndex(tick);
- scrollPane.getVerticalScrollBar().setValue(index * getRowHeight());
- getSelectionModel().setSelectionInterval(index, index);
- }
- }
-
- /**
* 新しい {@link MidiSequenceEditorDialog} を構築します。
* @param playlistTableModel このエディタが参照するプレイリストモデル
* @param outputMidiDevice イベントテーブルの操作音出力先MIDIデバイス
* @param midiDeviceDialogOpenAction MIDIデバイスダイアログを開くアクション
*/
public MidiSequenceEditorDialog(PlaylistTableModel playlistTableModel, VirtualMidiDevice outputMidiDevice, Action midiDeviceDialogOpenAction) {
- this.outputMidiDevice = outputMidiDevice;
- sequenceListTable = new SequenceListTable(playlistTableModel, midiDeviceDialogOpenAction);
- trackListTable = new TrackListTable(playlistTableModel.emptyTrackListTableModel);
- eventListTable = new EventListTable(playlistTableModel.emptyEventListTableModel);
+ sequenceListTable = new PlaylistTable(playlistTableModel, midiDeviceDialogOpenAction);
+ trackListTable = new SequenceTrackListTable(playlistTableModel.emptyTrackListTableModel);
+ eventListTable = new MidiEventTable(playlistTableModel.emptyEventListTableModel, outputMidiDevice);
newSequenceDialog = new NewSequenceDialog(playlistTableModel, outputMidiDevice);
setTitle("MIDI Editor/Playlist - "+ChordHelperApplet.VersionInfo.NAME);
setBounds( 150, 200, 900, 500 );
}
if(sequenceListTable.base64EncodeAction != null) {
add(Box.createRigidArea(new Dimension(5, 0)));
- add(new JButton(sequenceListTable.base64EncodeAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
+ add(new JButton(sequenceListTable.base64EncodeAction) {
+ { setMargin(ChordHelperApplet.ZERO_INSETS); }
+ });
}
add(Box.createRigidArea(new Dimension(5, 0)));
add(new JButton(playlistTableModel.getMoveToTopAction()) {
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
+import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JRootPane;
/**
* プレイリストビュー(シーケンスリスト)
*/
-public class SequenceListTable extends JTable {
- /**
- * ファイル選択ダイアログ(アプレットの場合は使用不可なのでnull)
- */
+public class PlaylistTable extends JTable {
+ /** ファイル選択ダイアログ(アプレットの場合は使用不可なのでnull) */
MidiFileChooser midiFileChooser;
- /**
- * BASE64エンコードアクション
- */
+ /** BASE64エンコードアクション */
Action base64EncodeAction;
- /**
- * BASE64ダイアログ
- */
+ /** BASE64ダイアログ */
public Base64Dialog base64Dialog;
- /**
- * MIDIデバイスダイアログを開くアクション
- */
+ /** MIDIデバイスダイアログを開くアクション */
private Action midiDeviceDialogOpenAction;
/**
* プレイリストビューを構築します。
* @param model プレイリストデータモデル
*/
- public SequenceListTable(PlaylistTableModel model, Action midiDeviceDialogOpenAction) {
+ public PlaylistTable(PlaylistTableModel model, Action midiDeviceDialogOpenAction) {
super(model, null, model.sequenceListSelectionModel);
this.midiDeviceDialogOpenAction = midiDeviceDialogOpenAction;
try {
}
@Override
public void actionPerformed(ActionEvent e) {
- SequenceTrackListTableModel mstm = getModel().getSelectedSequenceModel();
+ SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel();
byte[] data = null;
String filename = null;
- if( mstm != null ) {
- filename = mstm.getFilename();
+ if( sequenceModel != null ) {
+ filename = sequenceModel.getFilename();
try {
- data = mstm.getMIDIdata();
+ data = sequenceModel.getMIDIdata();
} catch (IOException ioe) {
base64Dialog.setText("File["+filename+"]:"+ioe.toString());
base64Dialog.setVisible(true);
) {
try {
getModel().loadToSequencer(row);
- } catch (InvalidMidiDataException|IllegalStateException e) {
+ } catch (InvalidMidiDataException|IllegalStateException ex) {
JOptionPane.showMessageDialog(
- SequenceListTable.this.getRootPane(),
- e,
+ table.getRootPane(), ex,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.ERROR_MESSAGE);
}
}
try {
model.loadToSequencer(row);
- } catch (InvalidMidiDataException e) {
+ } catch (InvalidMidiDataException ex) {
JOptionPane.showMessageDialog(
- SequenceListTable.this.getRootPane(),
- e,
+ table.getRootPane(), ex,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.ERROR_MESSAGE);
}
}
}
/**
- * このプレイリスト(シーケンスリスト)が表示するデータを提供する
- * プレイリストモデルを返します。
+ * このプレイリスト(シーケンスリスト)が表示するデータを提供するプレイリストモデルを返します。
* @return プレイリストモデル
*/
@Override
- public PlaylistTableModel getModel() {
- return (PlaylistTableModel)super.getModel();
- }
+ public PlaylistTableModel getModel() { return (PlaylistTableModel)dataModel; }
/**
* このプレイリストにMIDIファイルを追加します。追加に失敗した場合はダイアログを表示し、
* 後続のMIDIファイルが残っていればそれを追加するかどうかをユーザに尋ねます。
if( midiFileChooser != null ) {
SequenceTrackListTableModel seqModel = model.getSelectedSequenceModel();
if( seqModel != null && seqModel.isModified() && JOptionPane.showConfirmDialog(
- SequenceListTable.this.getRootPane(),
+ ((JComponent)event.getSource()).getRootPane(),
CONFIRM_MESSAGE,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION
) return;
}
- if( model.sequenceListSelectionModel.isSelectionEmpty() ) return;
- int index = model.sequenceListSelectionModel.getMinSelectionIndex();
- try {
- model.remove(index);
+ if( ! model.sequenceListSelectionModel.isSelectionEmpty() ) try {
+ model.remove(model.sequenceListSelectionModel.getMinSelectionIndex());
} catch (Exception ex) {
JOptionPane.showMessageDialog(
- SequenceListTable.this.getRootPane(),
+ ((JComponent)event.getSource()).getRootPane(),
ex,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.ERROR_MESSAGE);
) {
@Override
public void actionPerformed(ActionEvent event) {
- SequenceListTable playlistView = SequenceListTable.this;
- SequenceTrackListTableModel sequenceModel = playlistView.getModel().getSelectedSequenceModel();
+ SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel();
if( sequenceModel == null ) return;
String fn = sequenceModel.getFilename();
if( fn != null && ! fn.isEmpty() ) setSelectedFile(new File(fn));
- if( showSaveDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return;
+ JRootPane rootPane = ((JComponent)event.getSource()).getRootPane();
+ if( showSaveDialog(rootPane) != JFileChooser.APPROVE_OPTION ) return;
File f = getSelectedFile();
if( f.exists() ) {
fn = f.getName();
if( JOptionPane.showConfirmDialog(
- playlistView.getRootPane(),
+ rootPane,
"Overwrite " + fn + " ?\n" + fn + " を上書きしてよろしいですか?",
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.YES_NO_OPTION,
}
catch( Exception ex ) {
JOptionPane.showMessageDialog(
- playlistView.getRootPane(),
- ex,
+ rootPane, ex,
ChordHelperApplet.VersionInfo.NAME,
JOptionPane.ERROR_MESSAGE);
}
{ putValue(Action.SHORT_DESCRIPTION, "Open MIDI file - MIDIファイルを開く"); }
@Override
public void actionPerformed(ActionEvent event) {
- SequenceListTable playlistView = SequenceListTable.this;
- JRootPane rootPane = playlistView.getRootPane();
+ JRootPane rootPane = ((JComponent)event.getSource()).getRootPane();
try {
if( showOpenDialog(rootPane) != JFileChooser.APPROVE_OPTION ) return;
} catch( HeadlessException ex ) {
ex.printStackTrace();
return;
}
- int firstIndex = playlistView.add(Arrays.asList(getSelectedFile()));
+ int firstIndex = PlaylistTable.this.add(Arrays.asList(getSelectedFile()));
try {
- PlaylistTableModel playlist = playlistView.getModel();
+ PlaylistTableModel playlist = getModel();
MidiSequencerModel sequencerModel = playlist.getSequencerModel();
if( sequencerModel.getSequencer().isRunning() ) return;
if( firstIndex >= 0 ) playlist.play(firstIndex);