OSDN Git Service

MIDI Device Connection から MIDI Editor へ意図しないオブジェクトを
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Tue, 10 May 2016 17:34:09 +0000 (02:34 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Tue, 10 May 2016 17:34:09 +0000 (02:34 +0900)
ドラッグ&ドロップしても NullPointerException が出ないようにした

src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/mididevice/MidiDeviceTreeView.java
src/camidion/chordhelper/mididevice/MidiOpenedDevicesView.java
src/camidion/chordhelper/mididevice/MidiTransceiverListModelList.java
src/camidion/chordhelper/midieditor/MidiSequenceEditor.java

index 04dc825..97f8455 100644 (file)
@@ -284,7 +284,7 @@ public class ChordHelperApplet extends JApplet {
         */
        public static class VersionInfo {
                public static final String      NAME = "MIDI Chord Helper";
-               public static final String      VERSION = "Ver.20160509.1";
+               public static final String      VERSION = "Ver.20160510.1";
                public static final String      COPYRIGHT = "Copyright (C) 2004-2016";
                public static final String      AUTHER = "@きよし - Akiyoshi Kamide";
                public static final String      URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
@@ -466,7 +466,7 @@ public class ChordHelperApplet extends JApplet {
                        }
                );
                deviceModelList.editorDialog.setIconImage(iconImage);
-               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, deviceModelList.editorDialog, true);
+               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, deviceModelList.editorDialog.dropTargetListener, true);
                keyboardPanel.setEventDialog(deviceModelList.editorDialog.eventDialog);
                midiConnectionDialog = new MidiDeviceDialog(deviceModelList);
                midiConnectionDialog.setIconImage(iconImage);
index 4ddaa6c..ff02560 100644 (file)
@@ -14,37 +14,36 @@ import java.awt.dnd.DragSourceListener;
 
 import javax.swing.JInternalFrame;
 import javax.swing.JTree;
+import javax.swing.ListModel;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 import javax.swing.event.InternalFrameListener;
 import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.TreeModel;
 
 /**
  * MIDIデバイスツリービュー
  */
 public class MidiDeviceTreeView extends JTree {
 
-       public static final DataFlavor TREE_FLAVOR  = new DataFlavor(TreeModel.class,"TreeModel");
+       public static final DataFlavor LIST_MODEL_FLAVOR  = new DataFlavor(ListModel.class,"ListModel");
 
        public class DraggingObject implements Transferable {
-               private DataFlavor flavors[] = {TREE_FLAVOR};
+               private DataFlavor flavors[] = {LIST_MODEL_FLAVOR};
                private MidiTransceiverListModel trxListModel;
                @Override
                public Object getTransferData(DataFlavor flavor) {
-                       return TREE_FLAVOR.equals(flavor) ? trxListModel : null;
+                       return flavor.getRepresentationClass().isInstance(trxListModel) ? trxListModel : null;
                }
                @Override
                public DataFlavor[] getTransferDataFlavors() { return flavors; }
                @Override
                public boolean isDataFlavorSupported(DataFlavor flavor) {
-                       return TREE_FLAVOR.equals(flavor);
+                       return flavors[0].equals(flavor);
                }
        };
        private DraggingObject draggingObject = new DraggingObject();
        /**
-        * このツリーからドラッグしたMIDIデバイスのドロップが成功し、
-        * MIDIデバイスが開かれたときに再描画するためのリスナー
+        * このツリーからドラッグしたMIDIデバイスのドロップが成功したときに再描画するためのリスナー
         */
        private DragSourceListener dragSourceListener = new DragSourceAdapter() {
                @Override
@@ -65,6 +64,8 @@ public class MidiDeviceTreeView extends JTree {
                @Override
                public void internalFrameClosing(InternalFrameEvent e) { repaint(); }
        };
+       @Override
+       public MidiDeviceTreeModel getModel() { return (MidiDeviceTreeModel) super.getModel(); }
        /**
         * MIDIデバイスツリービューを構築します。
         * @param model このビューにデータを提供するモデル
@@ -78,10 +79,9 @@ public class MidiDeviceTreeView extends JTree {
                                        if( (dge.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) return;
                                        Point origin = dge.getDragOrigin();
                                        Object leaf = getPathForLocation(origin.x, origin.y).getLastPathComponent();
-                                       if( leaf instanceof MidiTransceiverListModel ) {
-                                               draggingObject.trxListModel = (MidiTransceiverListModel)leaf;
-                                               dge.startDrag(DragSource.DefaultMoveDrop, draggingObject, dragSourceListener);
-                                       }
+                                       if( ! (leaf instanceof MidiTransceiverListModel) ) return;
+                                       draggingObject.trxListModel = (MidiTransceiverListModel)leaf;
+                                       dge.startDrag(DragSource.DefaultMoveDrop, draggingObject, dragSourceListener);
                                }
                        }
                );
@@ -102,6 +102,4 @@ public class MidiDeviceTreeView extends JTree {
                // 初期状態でツリーノードを開いた状態にする
                for( int row = 0; row < getRowCount() ; row++ ) expandRow(row);
        }
-       @Override
-       public MidiDeviceTreeModel getModel() { return (MidiDeviceTreeModel) super.getModel(); }
 }
index da9a7e7..ea79610 100644 (file)
@@ -10,6 +10,8 @@ import java.awt.dnd.DropTargetListener;
 import java.awt.event.ComponentAdapter;
 import java.awt.event.ComponentEvent;
 import java.beans.PropertyVetoException;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.sound.midi.MidiUnavailableException;
 import javax.swing.JDesktopPane;
@@ -24,6 +26,9 @@ import javax.swing.tree.TreePath;
  * 開いている MIDI デバイスを置くためのデスクトップビュー
  */
 public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelectionListener {
+
+       private Map<MidiTransceiverListModel, MidiDeviceFrame> modelToFrame = new HashMap<>();
+
        /**
         * ツリー上で選択状態が変わったとき、このデスクトップ上のフレームの選択状態に反映します。
         */
@@ -35,10 +40,9 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                        if( lastSelected instanceof MidiTransceiverListModel ) {
                                MidiTransceiverListModel deviceModel = (MidiTransceiverListModel)lastSelected;
                                if( deviceModel.getMidiDevice().isOpen() ) {
-                                       // 開いているMIDIデバイスがツリー上で選択されたら
-                                       // このデスクトップでも選択する
+                                       // 開いているMIDIデバイスがツリー上で選択されたら、対応するフレームを選択
                                        try {
-                                               getMidiDeviceFrameOf(deviceModel).setSelected(true);
+                                               modelToFrame.get(deviceModel).setSelected(true);
                                        } catch( PropertyVetoException ex ) {
                                                ex.printStackTrace();
                                        }
@@ -46,8 +50,7 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                                }
                        }
                }
-               // 閉じているMIDIデバイス、またはMIDIデバイス以外のノードがツリー上で選択されたら
-               // このデスクトップ上のMIDIデバイスフレームをすべて非選択にする
+               // それ以外が選択されたら、現在選択されているフレームを非選択
                JInternalFrame frame = getSelectedFrame();
                if( ! (frame instanceof MidiDeviceFrame) ) return;
                try {
@@ -56,31 +59,13 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                        ex.printStackTrace();
                }
        }
-
-       /**
-        * 指定されたMIDIデバイスモデルに対するMIDIデバイスフレームを返します。
-        *
-        * @param deviceModel MIDIデバイスモデル
-        * @return 対応するMIDIデバイスフレーム(ない場合 null)
-        */
-       private MidiDeviceFrame getMidiDeviceFrameOf(MidiTransceiverListModel deviceModel) {
-               JInternalFrame[] frames = getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER);
-               for( JInternalFrame frame : frames ) {
-                       if( ! (frame instanceof MidiDeviceFrame) ) continue;
-                       MidiDeviceFrame deviceFrame = (MidiDeviceFrame)frame;
-                       if( deviceFrame.getMidiTransceiverListView().getModel().equals(deviceModel) ) {
-                               return deviceFrame;
-                       }
-               }
-               return null;
-       }
        /**
         * ツリー表示からこのデスクトップにドロップされたMIDIデバイスモデルに対応するフレームを表示するためのリスナー
         */
        private DropTargetListener dropTargetListener = new DropTargetAdapter() {
                @Override
                public void dragEnter(DropTargetDragEvent dtde) {
-                       if( dtde.getTransferable().isDataFlavorSupported(MidiDeviceTreeView.TREE_FLAVOR) ) {
+                       if( dtde.getTransferable().isDataFlavorSupported(MidiDeviceTreeView.LIST_MODEL_FLAVOR) ) {
                                dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
                        }
                }
@@ -94,11 +79,11 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                                        return;
                                }
                                Transferable t = dtde.getTransferable();
-                               if( ! t.isDataFlavorSupported(MidiDeviceTreeView.TREE_FLAVOR) ) {
+                               if( ! t.isDataFlavorSupported(MidiDeviceTreeView.LIST_MODEL_FLAVOR) ) {
                                        dtde.dropComplete(false);
                                        return;
                                }
-                               Object data = t.getTransferData(MidiDeviceTreeView.TREE_FLAVOR);
+                               Object data = t.getTransferData(MidiDeviceTreeView.LIST_MODEL_FLAVOR);
                                if( ! (data instanceof MidiTransceiverListModel) ) {
                                        dtde.dropComplete(false);
                                        return;
@@ -137,7 +122,7 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                                // デバイスが正常に開かれたことを確認できたら
                                // ドロップした場所へフレームを配置して可視化する。
                                //
-                               MidiDeviceFrame deviceFrame = getMidiDeviceFrameOf(deviceModel);
+                               MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
                                deviceFrame.setLocation(dtde.getLocation());
                                deviceFrame.setVisible(true);
                        }
@@ -164,8 +149,11 @@ public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelection
                int toY = 10;
                MidiTransceiverListModelList deviceModels = deviceTreeView.getModel().getTransceiverListModelList();
                for( MidiTransceiverListModel deviceModel : deviceModels ) {
-                       deviceModel.addListDataListener(cablePane.midiConnecterListDataListener);
                        MidiDeviceFrame frame = new MidiDeviceFrame(new MidiTransceiverListView(deviceModel, cablePane));
+                       modelToFrame.put(deviceModel, frame);
+                       //
+                       // MIDIデバイスモデルのMIDIコネクタリストが変化したときにMIDIケーブルを再描画
+                       deviceModel.addListDataListener(cablePane.midiConnecterListDataListener);
                        //
                        // デバイスフレームが開閉したときの動作
                        frame.addInternalFrameListener(cablePane.midiDeviceFrameListener);
index 7c8a93d..01df8f0 100644 (file)
@@ -13,8 +13,8 @@ import camidion.chordhelper.ChordHelperApplet;
 import camidion.chordhelper.midieditor.MidiSequenceEditor;
 
 /**
- * すべてのMIDIデバイスモデル {@link MidiTransceiverListModel} を収容するリストです。
- * {@link MidiDeviceTreeModel} もこのリストを参照します。
+ * 仮想MIDIデバイスを含めた、すべてのMIDIデバイスモデル {@link MidiTransceiverListModel}
+ * を収容するリストです。{@link MidiDeviceTreeModel} もこのリストを参照します。
  */
 public class MidiTransceiverListModelList extends Vector<MidiTransceiverListModel> {
 
index 8c6b57c..6a21231 100644 (file)
@@ -9,9 +9,9 @@ import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
 import java.awt.dnd.DropTargetDragEvent;
 import java.awt.dnd.DropTargetDropEvent;
-import java.awt.dnd.DropTargetEvent;
 import java.awt.dnd.DropTargetListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ComponentAdapter;
@@ -79,10 +79,10 @@ import camidion.chordhelper.music.MIDISpec;
  * MIDIエディタ(MIDI Editor/Playlist for MIDI Chord Helper)
  *
  * @author
- *     Copyright (C) 2006-2014 Akiyoshi Kamide
+ *     Copyright (C) 2006-2016 Akiyoshi Kamide
  *     http://www.yk.rim.or.jp/~kamide/music/chordhelper/
  */
-public class MidiSequenceEditor extends JDialog implements DropTargetListener {
+public class MidiSequenceEditor extends JDialog {
        private static VirtualMidiDevice virtualMidiDevice = new AbstractVirtualMidiDevice() {
                {
                        info = new MyInfo();
@@ -162,38 +162,37 @@ public class MidiSequenceEditor extends JDialog implements DropTargetListener {
                        JOptionPane.WARNING_MESSAGE
                ) == JOptionPane.YES_OPTION ;
        }
-       @Override
-       public void dragEnter(DropTargetDragEvent event) {
-               if( event.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ) {
-                       event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
-               }
-       }
-       @Override
-       public void dragExit(DropTargetEvent event) {}
-       @Override
-       public void dragOver(DropTargetDragEvent event) {}
-       @Override
-       public void dropActionChanged(DropTargetDragEvent event) {}
-       @Override
-       @SuppressWarnings("unchecked")
-       public void drop(DropTargetDropEvent event) {
-               event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
-               try {
-                       int action = event.getDropAction();
-                       if ( (action & DnDConstants.ACTION_COPY_OR_MOVE) != 0 ) {
-                               Transferable t = event.getTransferable();
-                               Object data = t.getTransferData(DataFlavor.javaFileListFlavor);
-                               loadAndPlay((List<File>)data);
-                               event.dropComplete(true);
-                               return;
+       /**
+        * ドロップされた複数のMIDIファイルを読み込むリスナー
+        */
+       public final DropTargetListener dropTargetListener = new DropTargetAdapter() {
+               @Override
+               public void dragEnter(DropTargetDragEvent event) {
+                       if( event.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ) {
+                               event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
                        }
-                       event.dropComplete(false);
                }
-               catch (Exception ex) {
-                       ex.printStackTrace();
+               @Override
+               @SuppressWarnings("unchecked")
+               public void drop(DropTargetDropEvent event) {
+                       event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+                       try {
+                               int action = event.getDropAction();
+                               if ( (action & DnDConstants.ACTION_COPY_OR_MOVE) != 0 ) {
+                                       Transferable t = event.getTransferable();
+                                       if( t.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ) {
+                                               loadAndPlay((List<File>)t.getTransferData(DataFlavor.javaFileListFlavor));
+                                               event.dropComplete(true);
+                                               return;
+                                       }
+                               }
+                       }
+                       catch (Exception ex) {
+                               ex.printStackTrace();
+                       }
                        event.dropComplete(false);
                }
-       }
+       };
        /**
         * 複数のMIDIファイルを読み込み、再生されていなかったら再生します。
         * すでに再生されていた場合、このエディタダイアログを表示します。
@@ -1225,7 +1224,7 @@ public class MidiSequenceEditor extends JDialog implements DropTargetListener {
                setTitle("MIDI Editor/Playlist - MIDI Chord Helper");
                setBounds( 150, 200, 900, 500 );
                setLayout(new FlowLayout());
-               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);
+               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetListener, true);
                JPanel playlistPanel = new JPanel() {{
                        JPanel playlistOperationPanel = new JPanel() {{
                                setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));