1 package camidion.chordhelper.mididevice;
3 import java.awt.datatransfer.Transferable;
4 import java.awt.dnd.DnDConstants;
5 import java.awt.dnd.DropTarget;
6 import java.awt.dnd.DropTargetAdapter;
7 import java.awt.dnd.DropTargetDragEvent;
8 import java.awt.dnd.DropTargetDropEvent;
9 import java.awt.dnd.DropTargetListener;
10 import java.awt.event.ComponentAdapter;
11 import java.awt.event.ComponentEvent;
12 import java.beans.PropertyVetoException;
13 import java.util.HashMap;
16 import javax.sound.midi.MidiUnavailableException;
17 import javax.swing.JDesktopPane;
18 import javax.swing.JInternalFrame;
19 import javax.swing.JLayeredPane;
20 import javax.swing.JOptionPane;
21 import javax.swing.event.TreeSelectionEvent;
22 import javax.swing.event.TreeSelectionListener;
23 import javax.swing.tree.TreePath;
26 * 開いている MIDI デバイスを置くためのデスクトップビュー
28 public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelectionListener {
30 private Map<MidiTransceiverListModel, MidiDeviceFrame> modelToFrame = new HashMap<>();
33 * ツリー上で選択状態が変わったとき、このデスクトップ上のフレームの選択状態に反映します。
36 public void valueChanged(TreeSelectionEvent tse) {
37 TreePath treePath = tse.getNewLeadSelectionPath();
38 if( treePath != null ) {
39 Object lastSelected = treePath.getLastPathComponent();
40 if( lastSelected instanceof MidiTransceiverListModel ) {
41 MidiTransceiverListModel deviceModel = (MidiTransceiverListModel)lastSelected;
42 if( deviceModel.getMidiDevice().isOpen() ) {
43 // 開いているMIDIデバイスがツリー上で選択されたら、対応するフレームを選択
44 MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
45 deviceFrame.toFront();
47 deviceFrame.setSelected(true);
48 } catch( PropertyVetoException ex ) {
55 // それ以外が選択されたら、現在選択されているフレームを非選択
56 JInternalFrame frame = getSelectedFrame();
57 if( ! (frame instanceof MidiDeviceFrame) ) return;
59 ((MidiDeviceFrame)frame).setSelected(false);
60 } catch( PropertyVetoException ex ) {
65 * ツリー表示からこのデスクトップにドロップされたMIDIデバイスモデルに対応するフレームを表示するためのリスナー
67 private DropTargetListener dropTargetListener = new DropTargetAdapter() {
69 public void dragEnter(DropTargetDragEvent dtde) {
70 if( dtde.getTransferable().isDataFlavorSupported(MidiDeviceTreeView.LIST_MODEL_FLAVOR) ) {
71 dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
75 public void drop(DropTargetDropEvent dtde) {
76 dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
78 int maskedBits = dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE;
79 if( maskedBits == 0 ) {
80 dtde.dropComplete(false);
83 Transferable t = dtde.getTransferable();
84 if( ! t.isDataFlavorSupported(MidiDeviceTreeView.LIST_MODEL_FLAVOR) ) {
85 dtde.dropComplete(false);
88 Object data = t.getTransferData(MidiDeviceTreeView.LIST_MODEL_FLAVOR);
89 if( ! (data instanceof MidiTransceiverListModel) ) {
90 dtde.dropComplete(false);
93 MidiTransceiverListModel deviceModel = (MidiTransceiverListModel)data;
95 deviceModel.getMidiDevice().open();
96 deviceModel.openReceiver();
97 } catch( MidiUnavailableException e ) {
101 // 例えば、「Microsort MIDI マッパー」と
102 // 「Microsoft GS Wavetable SW Synth」を
105 String title = "Cannot open MIDI device";
106 String message = "MIDIデバイス "+deviceModel+" はすでに使用中です。\n"
107 +"他のデバイスが連動して開いている可能性があります。\n\n"
109 dtde.dropComplete(false);
110 JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
113 if( ! deviceModel.getMidiDevice().isOpen() ) {
114 // 例外が出なかったにも関わらずデバイスが開かれていない場合
115 String title = "Cannot open MIDI device";
116 String message = "MIDIデバイス "+deviceModel+" はすでに使用中です。\n"
117 +"他のデバイスが連動して開いている可能性があります。\n\n" ;
118 dtde.dropComplete(false);
119 JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
122 dtde.dropComplete(true);
124 // デバイスが正常に開かれたことを確認できたら
125 // ドロップした場所へフレームを配置して可視化する。
127 MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
128 deviceFrame.setLocation(dtde.getLocation());
129 deviceFrame.setVisible(true);
131 catch (Exception ex) {
132 ex.printStackTrace();
133 dtde.dropComplete(false);
138 private MidiCablePane cablePane = new MidiCablePane(this);
140 public MidiOpenedDevicesView(
141 MidiDeviceTreeView deviceTreeView,
142 MidiDeviceInfoPane deviceInfoPane,
143 MidiDeviceDialog dialog
145 add(cablePane, JLayeredPane.PALETTE_LAYER);
146 addComponentListener(new ComponentAdapter() {
148 public void componentResized(ComponentEvent e) { cablePane.setSize(getSize()); }
152 MidiTransceiverListModelList deviceModels = deviceTreeView.getModel().getTransceiverListModelList();
153 for( MidiTransceiverListModel deviceModel : deviceModels ) {
154 MidiDeviceFrame frame = new MidiDeviceFrame(new MidiTransceiverListView(deviceModel, cablePane));
155 modelToFrame.put(deviceModel, frame);
157 // MIDIデバイスモデルのMIDIコネクタリストが変化したときにMIDIケーブルを再描画
158 deviceModel.addListDataListener(cablePane.midiConnecterListDataListener);
160 // デバイスフレームが開閉したときの動作
161 frame.addInternalFrameListener(cablePane.midiDeviceFrameListener);
162 frame.addInternalFrameListener(deviceTreeView.midiDeviceFrameListener);
163 frame.addInternalFrameListener(deviceInfoPane.midiDeviceFrameListener);
166 frame.addComponentListener(cablePane.midiDeviceFrameComponentListener);
169 dialog.addWindowListener(frame.windowListener);
171 frame.setSize(250, 90);
173 if( deviceModel.getMidiDevice().isOpen() ) {
174 frame.setLocation(toX, toY);
175 frame.setVisible(true);
176 toX = (toX == 10 ? 270 : 10);
180 new DropTarget( this, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetListener, true );