1 package camidion.chordhelper.midieditor;
3 import java.awt.Container;
4 import java.awt.Dimension;
5 import java.awt.FlowLayout;
6 import java.awt.datatransfer.DataFlavor;
7 import java.awt.event.ActionEvent;
11 import javax.sound.midi.Sequencer;
12 import javax.swing.AbstractAction;
13 import javax.swing.Action;
14 import javax.swing.Box;
15 import javax.swing.BoxLayout;
16 import javax.swing.Icon;
17 import javax.swing.JButton;
18 import javax.swing.JCheckBox;
19 import javax.swing.JComboBox;
20 import javax.swing.JDialog;
21 import javax.swing.JLabel;
22 import javax.swing.JOptionPane;
23 import javax.swing.JPanel;
24 import javax.swing.JScrollPane;
25 import javax.swing.JSplitPane;
26 import javax.swing.TransferHandler;
27 import javax.swing.border.EtchedBorder;
29 import camidion.chordhelper.ButtonIcon;
30 import camidion.chordhelper.ChordHelperApplet;
31 import camidion.chordhelper.mididevice.MidiSequencerModel;
32 import camidion.chordhelper.mididevice.VirtualMidiDevice;
35 * MIDIエディタ(MIDI Editor/Playlist for MIDI Chord Helper)
38 * Copyright (C) 2006-2017 Akiyoshi Kamide
39 * http://www.yk.rim.or.jp/~kamide/music/chordhelper/
41 public class MidiSequenceEditorDialog extends JDialog {
43 * このダイアログを開きます。表示されていなければ表示し、すでに表示されていたら最前面に移動します。
45 public void open() { if( isVisible() ) toFront(); else setVisible(true); }
47 * このダイアログを表示するボタン用アクション
49 public final Action openAction = new AbstractAction("Edit/Playlist/Speed", new ButtonIcon(ButtonIcon.EDIT_ICON)) {
51 String tooltip = "MIDIシーケンスの編集/プレイリスト/再生速度調整";
52 putValue(Action.SHORT_DESCRIPTION, tooltip);
55 public void actionPerformed(ActionEvent e) { open(); }
58 * ドロップされた複数のMIDIファイルを読み込むハンドラー
60 public final TransferHandler transferHandler = new TransferHandler() {
62 public boolean canImport(TransferSupport support) {
63 return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
65 @SuppressWarnings("unchecked")
67 public boolean importData(TransferSupport support) {
69 Object data = support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
70 play((List<File>)data);
72 } catch (Exception ex) {
73 JOptionPane.showMessageDialog(
74 MidiSequenceEditorDialog.this, ex,
75 ChordHelperApplet.VersionInfo.NAME,
76 JOptionPane.ERROR_MESSAGE);
84 public PlaylistTable playlistTable;
86 * このエディタダイアログが表示しているプレイリストモデルを返します。
89 public PlaylistTableModel getPlaylistModel() {
90 return playlistTable.getModel();
93 * 指定されたリストに格納されたMIDIファイルを読み込んで再生します。
94 * すでに再生されていた場合、このエディタダイアログを表示します。
95 * @param fileList 読み込むMIDIファイルのリスト
97 public void play(List<File> fileList) {
98 play(playlistTable.add(fileList));
101 * 指定されたインデックス値(先頭が0)のMIDIシーケンスから再生します。
102 * すでに再生されていた場合、このエディタダイアログを表示します。
103 * @param index プレイリスト内にあるMIDIシーケンスのインデックス値
105 public void play(int index) {
107 PlaylistTableModel playlist = getPlaylistModel();
108 MidiSequencerModel sequencerModel = playlist.getSequencerModel();
109 if( sequencerModel.getSequencer().isRunning() ) { open(); return; }
111 playlist.play(index);
112 playlistTable.getSelectionModel().setSelectionInterval(index, index);
114 } catch (Exception e) {
115 JOptionPane.showMessageDialog(this, e, ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
119 * 現在選択されているMIDIシーケンスから再生します。
120 * すでに再生されていた場合、このエディタダイアログを表示します。
123 play(playlistTable.getSelectionModel().getMinSelectionIndex());
126 static final Icon deleteIcon = new ButtonIcon(ButtonIcon.X_ICON);
128 * 新しいMIDIシーケンスを生成するダイアログ
130 public NewSequenceDialog newSequenceDialog;
132 * 新しい {@link MidiSequenceEditorDialog} を構築します。
133 * @param playlistTableModel このエディタが参照するプレイリストモデル
134 * @param eventDialog MIDIイベント入力ダイアログ
135 * @param outputMidiDevice イベントテーブルの操作音出力先MIDIデバイス
136 * @param midiDeviceDialogOpenAction MIDIデバイスダイアログを開くアクション
138 public MidiSequenceEditorDialog(PlaylistTableModel playlistTableModel, MidiEventDialog eventDialog, VirtualMidiDevice outputMidiDevice, Action midiDeviceDialogOpenAction) {
139 MidiEventTable eventListTable = new MidiEventTable(playlistTableModel.emptyEventListTableModel, eventDialog, outputMidiDevice);
140 SequenceTrackListTable trackListTable = new SequenceTrackListTable(playlistTableModel.emptyTrackListTableModel, eventListTable);
141 playlistTable = new PlaylistTable(playlistTableModel, midiDeviceDialogOpenAction, trackListTable);
142 newSequenceDialog = new NewSequenceDialog(playlistTable, outputMidiDevice);
143 setTitle("MIDI Editor/Playlist - "+ChordHelperApplet.VersionInfo.NAME);
144 setBounds( 150, 200, 900, 500 );
145 setLayout(new FlowLayout());
146 setTransferHandler(transferHandler);
149 JPanel playlistPanel = new JPanel() {{
150 JPanel playlistOperationPanel = new JPanel() {{
151 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
152 add(Box.createRigidArea(new Dimension(10, 0)));
153 add(new JButton(newSequenceDialog.openAction) {
154 { setMargin(ChordHelperApplet.ZERO_INSETS); }
156 if( playlistTable.midiFileChooser != null ) {
157 add( Box.createRigidArea(new Dimension(5, 0)) );
158 add(new JButton(playlistTable.midiFileChooser.openMidiFileAction) {
159 { setMargin(ChordHelperApplet.ZERO_INSETS); }
162 add(Box.createRigidArea(new Dimension(5, 0)));
163 add(new JButton(playlistTable.base64EncodeAction) {
164 { setMargin(ChordHelperApplet.ZERO_INSETS); }
166 add(Box.createRigidArea(new Dimension(5, 0)));
167 add(new JButton(playlistTableModel.getMoveToTopAction()) {
168 { setMargin(ChordHelperApplet.ZERO_INSETS); }
170 add(Box.createRigidArea(new Dimension(5, 0)));
171 add(new JButton(playlistTableModel.getMoveToBottomAction()) {
172 { setMargin(ChordHelperApplet.ZERO_INSETS); }
174 if( playlistTable.midiFileChooser != null ) {
175 add(Box.createRigidArea(new Dimension(5, 0)));
176 add(new JButton(playlistTable.midiFileChooser.saveMidiFileAction) {
177 { setMargin(ChordHelperApplet.ZERO_INSETS); }
180 add( Box.createRigidArea(new Dimension(5, 0)) );
181 add(new JButton(playlistTable.deleteSequenceAction) {
182 { setMargin(ChordHelperApplet.ZERO_INSETS); }
184 add( Box.createRigidArea(new Dimension(5, 0)) );
185 add(new SequencerSpeedSlider(playlistTableModel.getSequencerModel().speedSliderModel));
186 add( Box.createRigidArea(new Dimension(5, 0)) );
188 setBorder(new EtchedBorder());
189 MidiSequencerModel sequencerModel = playlistTableModel.getSequencerModel();
190 add(new JLabel("Sync Master"));
191 add(new JComboBox<Sequencer.SyncMode>(sequencerModel.masterSyncModeModel));
192 add(new JLabel("Slave"));
193 add(new JComboBox<Sequencer.SyncMode>(sequencerModel.slaveSyncModeModel));
196 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
197 add(new JScrollPane(playlistTable));
198 add(Box.createRigidArea(new Dimension(0, 10)));
199 add(playlistOperationPanel);
200 add(Box.createRigidArea(new Dimension(0, 10)));
202 JPanel trackListPanel = new JPanel() {{
203 JPanel trackListOperationPanel = new JPanel() {{
204 add(new JButton(trackListTable.addTrackAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
205 add(new JButton(trackListTable.deleteTrackAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
207 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
208 add(trackListTable.titleLabel);
209 add(Box.createRigidArea(new Dimension(0, 5)));
210 add(new JScrollPane(trackListTable));
211 add(Box.createRigidArea(new Dimension(0, 5)));
212 add(trackListOperationPanel);
214 JPanel eventListPanel = new JPanel() {{
215 JPanel eventListOperationPanel = new JPanel() {{
216 add(new JCheckBox("Pair NoteON/OFF") {{
217 setModel(eventListTable.pairNoteOnOffModel);
218 setToolTipText("NoteON/OFFをペアで同時選択する");
220 add(new JButton(eventListTable.queryJumpEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
221 add(new JButton(eventListTable.queryAddEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
222 add(new JButton(eventListTable.copyEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
223 add(new JButton(eventListTable.cutEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
224 add(new JButton(eventListTable.queryPasteEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
225 add(new JButton(eventListTable.deleteEventAction) {{ setMargin(ChordHelperApplet.ZERO_INSETS); }});
227 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
228 add(eventListTable.titleLabel);
229 add(eventListTable.scrollPane);
230 add(eventListOperationPanel);
232 Container cp = getContentPane();
233 cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
234 cp.add(Box.createVerticalStrut(2));
236 new JSplitPane(JSplitPane.VERTICAL_SPLIT, playlistPanel,
237 new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, trackListPanel, eventListPanel) {{
238 setDividerLocation(300);
241 setDividerLocation(160);