import java.awt.Dimension;
import java.awt.Image;
import java.awt.Insets;
-import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20160630.1";
+ public static final String VERSION = "Ver.20160702.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/";
(midiEditor = new MidiSequenceEditor(playlistModel, guiMidiDevice)).setIconImage(iconImage);
//
// メイン画面へのMIDIファイルのドラッグ&ドロップ受付開始
- new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, midiEditor.dropTargetListener, true);
+ setTransferHandler(midiEditor.transferHandler);
//
// MIDIエディタのイベントダイアログを、ピアノ鍵盤のイベント送出ダイアログと共用
keyboardPanel.setEventDialog(midiEditor.eventDialog);
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;
+import javax.swing.DropMode;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
return (AbstractTransceiverListModel<E>) super.getModel();
}
/**
- * このリストの座標系内の指定された位置にある要素を返します。
+ * このリストの座標系内の指定された位置にある最寄りの要素を返します。
* @param p 位置
*/
public E getElementAt(Point p) {
return this;
}
});
+ setDragEnabled(true);
+ setDropMode(DropMode.ON);
}
}
+++ /dev/null
-package camidion.chordhelper.mididevice;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.sound.midi.Receiver;
-import javax.sound.midi.Transmitter;
-
-/**
- * ドラッグ&ドロップで転送する{@link Transmitter}または{@link Receiver}の収容箱
- */
-public class DraggingTransceiver implements Transferable {
- public static final DataFlavor receiverFlavor = new DataFlavor(Receiver.class, "Receiver");
- public static final DataFlavor transmitterFlavor = new DataFlavor(Transmitter.class, "Transmitter");
- private static final List<DataFlavor> flavors = Arrays.asList(transmitterFlavor, receiverFlavor);
- private Object data;
- public Object getData() { return data; }
- public void setData(Object data) { this.data = data; }
- @Override
- public Object getTransferData(DataFlavor flavor) {
- return flavor.getRepresentationClass().isInstance(data) ? data : null;
- }
- @Override
- public DataFlavor[] getTransferDataFlavors() { return (DataFlavor[]) flavors.toArray(); }
- @Override
- public boolean isDataFlavorSupported(DataFlavor flavor) { return flavors.contains(flavor); }
-}
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceMotionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
* MIDI ケーブル描画面
*/
public class MidiCablePane extends JComponent {
- static DraggingTransceiver dragging = new DraggingTransceiver();
+ private Object dragSourceTransceiver;
+ private Object dragDestinationTransceiver;
private Point draggingPoint;
/**
- * ドラッグ中の場所を更新し、再描画を予約します。
- * @param p ドラッグ中の場所(ドラッグ&ドロップ終了時はnullを指定)
+ * ドラッグ元の{@link Transmitter}または{@link Receiver}を設定します。
+ *
+ * @param trx ドラッグ元
*/
- public void updateDraggingLocation(Point p) {
- if( (draggingPoint = p) == null ) {
- dragging.setData(null);
- } else {
- Point origin = getLocationOnScreen();
- draggingPoint.translate(-origin.x, -origin.y);
+ public void setDragSourceTransceiver(Object trx) {
+ if( (dragSourceTransceiver = trx) == null ) {
+ draggingPoint = null;
+ dragDestinationTransceiver = null;
}
repaint();
}
/**
+ * ドラッグ元の{@link Transmitter}または{@link Receiver}を返します。
+ */
+ public Object getDragSourceTransceiver() { return dragSourceTransceiver; }
+ /**
+ * ドラッグ先の{@link Transmitter}または{@link Receiver}を設定します。
+ * @param dragDestinationTransceiver 設定するドラッグ先
+ */
+ public void setDragDestinationTransceiver(Object dragDestinationTransceiver) {
+ this.dragDestinationTransceiver = dragDestinationTransceiver;
+ }
+ /**
+ * ドラッグ先の{@link Transmitter}または{@link Receiver}を返します。
+ */
+ public Object getDragDestinationTranceiver() { return dragDestinationTransceiver; }
+ /**
* {@link MidiDeviceFrame} が移動または変形したときにケーブルを再描画するためのリスナー
*/
public final ComponentListener midiDeviceFrameComponentListener = new ComponentAdapter() {
this.desktopPane = desktopPane;
setOpaque(false);
setVisible(true);
+ DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
+ @Override
+ public void dragMouseMoved(DragSourceDragEvent dsde) {
+ // OSのスクリーン座標系から、このケーブル画面の座標系に変換する
+ Point origin = getLocationOnScreen();
+ (draggingPoint = dsde.getLocation()).translate(-origin.x, -origin.y);
+ repaint();
+ }
+ });
}
private static final Stroke CABLE_STROKE = new BasicStroke(
3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+ private static final float dash[] = {1.0f, 5.0f};
+ private static final Stroke VIRTUAL_CABLE_STROKE = new BasicStroke(
+ 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, dash, 0.0f);
private static final List<Color> CABLE_COLORS = Arrays.asList(
new Color(255, 0, 0,144),
new Color(0, 255, 0,144),
new Color(0,191,191,144),
new Color(191,0,191,144)
);
- private static final Color ADDING_CABLE_COLOR = new Color(0, 0, 0, 144);
- private static final Color REMOVING_CABLE_COLOR = new Color(128, 128, 128, 144);
+ private static final Color NEW_CABLE_COLOR = new Color(0, 0, 0, 144);
private Hashtable<Receiver,Color> colorMap = new Hashtable<>();
private Color colorOf(Receiver rx) {
Color color = colorMap.get(rx);
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
- g2.setStroke(CABLE_STROKE);
JInternalFrame[] frames = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER);
for( JInternalFrame frame : frames ) {
if( ! (frame instanceof MidiDeviceFrame) ) continue;
MidiDeviceModel fromDeviceModel = fromFrame.getMidiDeviceModel();
//
// Receiverからドラッグされている線を描画
- if( draggingPoint != null && fromDeviceModel.getMidiDevice().getReceivers().contains(dragging.getData()) ) {
- Receiver rx = (Receiver)dragging.getData();
+ if( draggingPoint != null && fromDeviceModel.getMidiDevice().getReceivers().contains(dragSourceTransceiver) ) {
+ Receiver rx = (Receiver)dragSourceTransceiver;
Rectangle rxBounds = fromFrame.getBoundsOf(rx);
if( rxBounds == null ) continue;
int r = (rxBounds.height - 5) / 2;
rxBounds.translate(r+4, r+4);
+ if( dragDestinationTransceiver instanceof Transmitter ) {
+ g2.setStroke(CABLE_STROKE);
+ } else {
+ g2.setStroke(VIRTUAL_CABLE_STROKE);
+ }
g2.setColor(colorOf(rx));
g2.drawLine(rxBounds.x, rxBounds.y, draggingPoint.x, draggingPoint.y);
}
if( txBounds == null ) continue;
int r = (txBounds.height - 5) / 2;
txBounds.translate(r+4, r+4);
- //
- // Transmitterに現在接続されているReceiverを把握
- Receiver rx = tx.getReceiver();
- if( draggingPoint != null && tx.equals(dragging.getData()) ) {
+ if( draggingPoint != null && tx.equals(dragSourceTransceiver) ) {
//
// Transmitterからドラッグされている線を描画
- g2.setColor(rx == null ? ADDING_CABLE_COLOR : colorOf(rx));
+ if( dragDestinationTransceiver instanceof Receiver ) {
+ g2.setStroke(CABLE_STROKE);
+ g2.setColor(colorOf((Receiver)dragDestinationTransceiver));
+ } else {
+ g2.setStroke(VIRTUAL_CABLE_STROKE);
+ g2.setColor(NEW_CABLE_COLOR);
+ }
g2.drawLine(txBounds.x, txBounds.y, draggingPoint.x, draggingPoint.y);
}
+ //
+ // スキャン中のTransmitterに現在接続されているReceiverを把握
+ Receiver rx = tx.getReceiver();
if( rx == null ) continue;
for( JInternalFrame toFrame : frames ) {
if( ! (toFrame instanceof MidiDeviceFrame) ) continue;
- //
- // Receiverの場所を特定
Rectangle rxBounds = ((MidiDeviceFrame)toFrame).getBoundsOf(rx);
if( rxBounds == null ) continue;
r = (rxBounds.height - 5) / 2;
rxBounds.translate(r+4, r+4);
//
// Transmitter⇔Receiver間の線を描画
- g2.setColor(tx.equals(dragging.getData()) ? REMOVING_CABLE_COLOR : colorOf(rx));
+ g2.setStroke(tx.equals(dragSourceTransceiver) ? VIRTUAL_CABLE_STROKE : CABLE_STROKE);
+ g2.setColor(colorOf(rx));
g2.drawLine(txBounds.x, txBounds.y, rxBounds.x, rxBounds.y);
break;
}
import javax.sound.midi.Transmitter;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
-import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
public Rectangle getBoundsOf(Transmitter tx) {
if( transmitterListView == null ) return null;
Rectangle rect = transmitterListView.getCellBounds(tx);
+ if( rect == null ) return null;
translate(rect, txPanel, transmitterListView);
return rect;
}
public Rectangle getBoundsOf(Receiver rx) {
if( receiverListView == null ) return null;
Rectangle rect = receiverListView.getCellBounds(rx);
+ if( rect == null ) return null;
translate(rect, rxPanel, receiverListView);
return rect;
}
- private void translate(Rectangle rect, JPanel panel, JList<? extends AutoCloseable> list) {
- if( rect == null ) return;
+ private void translate(Rectangle rect, JPanel panel, AbstractTransceiverListView<?> list) {
int x = getX() + getRootPane().getX() + getContentPane().getX() +
scrollPane.getX() + trxPanel.getX() +
panel.getX() + list.getX();
package camidion.chordhelper.mididevice;
import java.awt.Component;
-import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DragGestureEvent;
-import java.awt.dnd.DragGestureListener;
-import java.awt.dnd.DragSource;
-import java.awt.dnd.DragSourceAdapter;
-import java.awt.dnd.DragSourceDropEvent;
+import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
+import javax.swing.TransferHandler;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
* MIDIデバイスツリービュー
*/
public class MidiDeviceTreeView extends JTree {
-
- public static final DataFlavor DEVICE_MODEL_FLAVOR = new DataFlavor(MidiDeviceModel.class,"MidiDeviceModel");
-
- public class DraggingDevice implements Transferable {
- private DataFlavor flavors[] = {DEVICE_MODEL_FLAVOR};
- private MidiDeviceModel midiDeviceModel;
- @Override
- public Object getTransferData(DataFlavor flavor) {
- return flavor.getRepresentationClass().isInstance(midiDeviceModel) ? midiDeviceModel : null;
- }
- @Override
- public DataFlavor[] getTransferDataFlavors() { return flavors; }
- @Override
- public boolean isDataFlavorSupported(DataFlavor flavor) {
- return flavors[0].equals(flavor);
- }
- };
- private DraggingDevice draggingDevice = new DraggingDevice();
+ public static final DataFlavor deviceModelFlavor = new DataFlavor(MidiDeviceModel.class,"MidiDeviceModel");
+ private static final DataFlavor flavors[] = {deviceModelFlavor};
/**
* {@link MidiDeviceFrame} が閉じられたり、選択されたりしたときに再描画するリスナー
*/
*/
public MidiDeviceTreeView(MidiDeviceTreeModel model) {
super(model);
- (new DragSource()).createDefaultDragGestureRecognizer(
- this, DnDConstants.ACTION_COPY_OR_MOVE, new DragGestureListener() {
- @Override
- public void dragGestureRecognized(DragGestureEvent dge) {
- 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 MidiDeviceModel) ) return;
- draggingDevice.midiDeviceModel = (MidiDeviceModel)leaf;
- dge.startDrag(DragSource.DefaultMoveDrop, draggingDevice, new DragSourceAdapter() {
- @Override
- public void dragDropEnd(DragSourceDropEvent dsde) {
- if( dsde.getDropSuccess() ) repaint();
- }
- });
- }
- }
- );
setCellRenderer(new DefaultTreeCellRenderer() {
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
//
// ツリーノードのToolTipを有効化
ToolTipManager.sharedInstance().registerComponent(this);
-
+ //
+ // ドラッグを有効化
+ setDragEnabled(true);
+ setTransferHandler(new TransferHandler() {
+ @Override
+ public int getSourceActions(JComponent c) { return COPY_OR_MOVE; }
+ @Override
+ protected Transferable createTransferable(JComponent c) {
+ JTree tree = (JTree) c;
+ Object node = tree.getLastSelectedPathComponent();
+ if( node instanceof MidiDeviceModel ) {
+ MidiDeviceModel midiDeviceModel = (MidiDeviceModel)node;
+ if( ! midiDeviceModel.getMidiDevice().isOpen() ) return new Transferable() {
+ @Override
+ public Object getTransferData(DataFlavor flavor) {
+ return flavor.getRepresentationClass().isInstance(midiDeviceModel) ? midiDeviceModel : null;
+ }
+ @Override
+ public DataFlavor[] getTransferDataFlavors() { return flavors; }
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavors[0].equals(flavor);
+ }
+ };
+ }
+ return null;
+ }
+ @Override
+ protected void exportDone(JComponent source, Transferable data, int action) {
+ if( action != NONE ) repaint();
+ }
+ });
}
}
package camidion.chordhelper.mididevice;
-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.DropTargetListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyVetoException;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
+import javax.swing.TransferHandler;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
/**
- * 開いている MIDI デバイスを置くためのデスクトップビュー
+ * 開いているMIDIデバイスを置くためのデスクトップビュー
*/
public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelectionListener {
-
+ /**
+ * MIDIデバイスモデルからフレームを割り出すためのマップ
+ */
private Map<MidiDeviceModel, MidiDeviceFrame> modelToFrame = new HashMap<>();
-
/**
* ツリー上で選択状態が変わったとき、このデスクトップ上のフレームの選択状態に反映します。
*/
ex.printStackTrace();
}
}
- /**
- * ツリー表示からこのデスクトップにドロップされたMIDIデバイスモデルに対応するフレームを表示するためのリスナー
- */
- private DropTargetListener dropTargetListener = new DropTargetAdapter() {
- @Override
- public void dragEnter(DropTargetDragEvent dtde) {
- if( dtde.getTransferable().isDataFlavorSupported(MidiDeviceTreeView.DEVICE_MODEL_FLAVOR) ) {
- dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
- }
- }
- @Override
- public void drop(DropTargetDropEvent dtde) {
- dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
- try {
- int maskedBits = dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE;
- if( maskedBits == 0 ) {
- dtde.dropComplete(false);
- return;
- }
- Transferable t = dtde.getTransferable();
- if( ! t.isDataFlavorSupported(MidiDeviceTreeView.DEVICE_MODEL_FLAVOR) ) {
- dtde.dropComplete(false);
- return;
- }
- Object source = t.getTransferData(MidiDeviceTreeView.DEVICE_MODEL_FLAVOR);
- if( ! (source instanceof MidiDeviceModel) ) {
- dtde.dropComplete(false);
- return;
- }
- MidiDeviceModel deviceModel = (MidiDeviceModel)source;
- try {
- deviceModel.open();
- } catch( MidiUnavailableException e ) {
- //
- // デバイスを開くのに失敗した場合
- //
- // 例えば、「Microsort MIDI マッパー」と
- // 「Microsoft GS Wavetable SW Synth」を
- // 同時に開こうとするとここに来る。
- //
- String title = "Cannot open MIDI device";
- String message = "MIDIデバイス "+deviceModel+" はすでに使用中です。\n"
- +"他のデバイスが連動して開いている可能性があります。\n\n"
- + e.getMessage();
- dtde.dropComplete(false);
- JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
- return;
- }
- if( ! deviceModel.getMidiDevice().isOpen() ) {
- // 例外が出なかったにも関わらずデバイスが開かれていない場合
- String title = "Cannot open MIDI device";
- String message = "MIDIデバイス "+deviceModel+" はすでに使用中です。\n"
- +"他のデバイスが連動して開いている可能性があります。\n\n" ;
- dtde.dropComplete(false);
- JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
- return;
- }
- //
- // デバイスが正常に開かれたことを確認できたら
- // ドロップした場所へフレームを配置して可視化する。
- //
- MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
- deviceFrame.setLocation(dtde.getLocation());
- deviceFrame.setVisible(true);
- dtde.dropComplete(true);
- }
- catch (Exception ex) {
- ex.printStackTrace();
- dtde.dropComplete(false);
- }
- }
- };
-
- MidiCablePane cablePane = new MidiCablePane(this);
public MidiOpenedDevicesView(MidiDeviceTreeView deviceTreeView,
MidiDeviceInfoPane deviceInfoPane, MidiDeviceDialog dialog)
{
+ MidiCablePane cablePane = new MidiCablePane(this);
add(cablePane, JLayeredPane.PALETTE_LAYER);
addComponentListener(new ComponentAdapter() {
@Override
toY += 50;
}
}
- new DropTarget( this, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetListener, true );
+ setTransferHandler(new TransferHandler() {
+ @Override
+ public boolean canImport(TransferSupport support) {
+ if( ! support.isDrop() ) return false;
+ if( support.isDataFlavorSupported(MidiDeviceTreeView.deviceModelFlavor) ) {
+ // MIDIデバイスを開くためのドロップを受け付ける
+ return true;
+ }
+ if( support.isDataFlavorSupported(TransmitterListView.elementFlavor) ) {
+ cablePane.setDragDestinationTransceiver(null);
+ // Transmitterの切り離しができるよう、ドロップを容認
+ return true;
+ }
+ if( support.isDataFlavorSupported(ReceiverListView.elementFlavor) ) {
+ cablePane.setDragDestinationTransceiver(null);
+ // Receiverはドロップ不可
+ }
+ return false;
+ }
+ @Override
+ public boolean importData(TransferSupport support) {
+ MidiDeviceModel deviceModel = null;
+ Object from;
+ try {
+ from = support.getTransferable().getTransferData(MidiDeviceTreeView.deviceModelFlavor);
+ if( ! (from instanceof MidiDeviceModel) ) return false;
+ deviceModel = (MidiDeviceModel)from;
+ deviceModel.open();
+ if( ! deviceModel.getMidiDevice().isOpen() ) {
+ throw new MidiUnavailableException("開いたはずなのに、開かれた状態になっていません。");
+ }
+ MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
+ if( ! deviceFrame.isVisible() ) {
+ deviceFrame.setLocation(support.getDropLocation().getDropPoint());
+ deviceFrame.setVisible(true);
+ }
+ return true;
+ } catch( MidiUnavailableException e ) {
+ //
+ // デバイスを開くのに失敗した場合
+ //
+ // 例えば、「Microsort MIDI マッパー」と「Microsoft GS Wavetable SW Synth」は
+ // 連動して開かれるため、同時に開こうとすると、ここにたどり着く。
+ //
+ String title = "Cannot open MIDI device";
+ String message = "MIDIデバイス "+deviceModel+" はすでに使用中です。\n"
+ +"他のデバイスが連動して開いている可能性があります。\n\n"
+ + e.getMessage();
+ JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
+ return false;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return false;
+ }
+ }
+ });
}
}
package camidion.chordhelper.mididevice;
+import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DragGestureEvent;
-import java.awt.dnd.DragGestureListener;
-import java.awt.dnd.DragSource;
-import java.awt.dnd.DragSourceAdapter;
-import java.awt.dnd.DragSourceDragEvent;
-import java.awt.dnd.DragSourceDropEvent;
-import java.awt.dnd.DragSourceMotionListener;
-import java.awt.dnd.DropTarget;
-import java.awt.dnd.DropTargetAdapter;
-import java.awt.dnd.DropTargetDragEvent;
-import java.awt.dnd.DropTargetDropEvent;
-import java.awt.dnd.DropTargetListener;
+import java.util.Arrays;
+import java.util.List;
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;
+import javax.swing.JComponent;
+import javax.swing.TransferHandler;
/**
* {@link Receiver}のリストビュー
*/
public class ReceiverListView extends AbstractTransceiverListView<Receiver> {
- @Override
- public ReceiverListModel getModel() { return (ReceiverListModel) super.getModel(); }
+ public static final DataFlavor elementFlavor = new DataFlavor(Receiver.class, "Receiver");
+ protected static final List<DataFlavor> flavors = Arrays.asList(elementFlavor);
@Override
protected String toolTipTextFor(Receiver rx) {
return "受信端子(Rx):ドラッグ&ドロップしてTxに接続できます。";
}
+ @Override
+ public ReceiverListModel getModel() { return (ReceiverListModel) super.getModel(); }
/**
* 仮想MIDI端子リストビューを生成します。
* @param model このビューから参照されるデータモデル
*/
public ReceiverListView(ReceiverListModel model, MidiCablePane cablePane) {
super(model);
- setupDrag(cablePane);
- setupDrop();
- }
- /**
- * {@link Receiver}をドラッグできるようにします。
- * @param cablePane MIDIケーブル描画面
- */
- private void setupDrag(MidiCablePane cablePane) {
- DragSource dragSource = new DragSource();
- DragGestureListener dgl = new DragGestureListener() {
+ setTransferHandler(new TransferHandler() {
+ @Override
+ public int getSourceActions(JComponent compo) { return COPY_OR_MOVE; }
@Override
- public void dragGestureRecognized(DragGestureEvent event) {
- if( (event.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) return;
- MidiCablePane.dragging.setData(getElementAt(event.getDragOrigin()));
- event.startDrag(DragSource.DefaultLinkDrop, MidiCablePane.dragging, new DragSourceAdapter() {
+ protected Transferable createTransferable(JComponent compo) {
+ cablePane.setDragSourceTransceiver(getSelectedValue());
+ return new Transferable() {
+ @Override
+ public Object getTransferData(DataFlavor flavor) {
+ return cablePane.getDragSourceTransceiver();
+ }
@Override
- public void dragDropEnd(DragSourceDropEvent dsde) {
- cablePane.updateDraggingLocation(null);
+ public DataFlavor[] getTransferDataFlavors() {
+ return (DataFlavor[]) flavors.toArray();
}
- });
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavors.contains(flavor);
+ }
+ };
}
- };
- dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
- dragSource.addDragSourceMotionListener(new DragSourceMotionListener() {
@Override
- public void dragMouseMoved(DragSourceDragEvent dsde) {
- cablePane.updateDraggingLocation(dsde.getLocation());
+ protected void exportDone(JComponent source, Transferable data, int action) {
+ cablePane.setDragSourceTransceiver(null);
}
- });
- }
- /**
- * {@link Transmitter}のドロップを受け付けます。
- */
- private void setupDrop() {
- DropTargetListener dtl = new DropTargetAdapter() {
@Override
- public void dragEnter(DropTargetDragEvent event) {
- if( event.isDataFlavorSupported(DraggingTransceiver.transmitterFlavor) ) {
- event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
+ public boolean canImport(TransferSupport support) {
+ if( ! support.isDrop() ) return false;
+ if( support.isDataFlavorSupported(TransmitterListView.elementFlavor) ) {
+ Receiver to = getElementAt(support.getDropLocation().getDropPoint());
+ cablePane.setDragDestinationTransceiver(to);
+ return true;
}
+ cablePane.setDragDestinationTransceiver(null);
+ return false;
}
@Override
- public void drop(DropTargetDropEvent event) {
- event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
- if( (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) {
- event.dropComplete(false);
- return;
- }
- Transferable t = event.getTransferable();
- if( ! t.isDataFlavorSupported(DraggingTransceiver.transmitterFlavor) ) {
- event.dropComplete(false);
- return;
- }
+ public boolean importData(TransferSupport support) {
try {
- Object tx = t.getTransferData(DraggingTransceiver.transmitterFlavor);
- if( tx != null ) {
- ((Transmitter)tx).setReceiver(getElementAt(event.getLocation()));
- event.dropComplete(true);
- return;
- }
+ Object from = support.getTransferable().getTransferData(TransmitterListView.elementFlavor);
+ if( ! (from instanceof Transmitter) ) return false;
+ Receiver to = getElementAt(support.getDropLocation().getDropPoint());
+ ((Transmitter)from).setReceiver(to);
+ return true;
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ return false;
}
- catch (Exception ex) {
- ex.printStackTrace();
- }
- event.dropComplete(false);
}
- };
- new DropTarget( this, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true );
+ });
}
}
package camidion.chordhelper.mididevice;
+import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DragGestureEvent;
-import java.awt.dnd.DragGestureListener;
-import java.awt.dnd.DragSource;
-import java.awt.dnd.DragSourceAdapter;
-import java.awt.dnd.DragSourceDragEvent;
-import java.awt.dnd.DragSourceDropEvent;
-import java.awt.dnd.DragSourceMotionListener;
-import java.awt.dnd.DropTarget;
-import java.awt.dnd.DropTargetAdapter;
-import java.awt.dnd.DropTargetDragEvent;
-import java.awt.dnd.DropTargetDropEvent;
-import java.awt.dnd.DropTargetListener;
+import java.util.Arrays;
+import java.util.List;
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;
+import javax.swing.JComponent;
+import javax.swing.TransferHandler;
/**
* {@link Transmitter}のリストビュー
*/
public class TransmitterListView extends AbstractTransceiverListView<Transmitter> {
- @Override
- public TransmitterListModel getModel() { return (TransmitterListModel) super.getModel(); }
+ public static final DataFlavor elementFlavor = new DataFlavor(Transmitter.class, "Transmitter");
+ protected static final List<DataFlavor> flavors = Arrays.asList(elementFlavor);
@Override
protected String toolTipTextFor(Transmitter tx) {
if( tx instanceof DummyTransmitter ) {
return "接続済の送信端子(Tx):ドラッグ&ドロップして接続先Rxを変更、または切断できます。";
}
}
+ @Override
+ public TransmitterListModel getModel() { return (TransmitterListModel) super.getModel(); }
/**
* 仮想MIDI端子リストビューを生成します。
* @param model このビューから参照されるデータモデル
*/
public TransmitterListView(TransmitterListModel model, MidiCablePane cablePane) {
super(model);
- setupDrag(cablePane);
- setupDrop();
- }
- /**
- * {@link Transmitter}をドラッグできるようにします。
- * @param cablePane MIDIケーブル描画面
- */
- private void setupDrag(MidiCablePane cablePane) {
- DragSource dragSource = new DragSource();
- DragGestureListener dgl = new DragGestureListener() {
+ setTransferHandler(new TransferHandler() {
+ @Override
+ public int getSourceActions(JComponent compo) { return COPY_OR_MOVE; }
@Override
- public void dragGestureRecognized(DragGestureEvent event) {
- if( (event.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) return;
- MidiCablePane.dragging.setData(getElementAt(event.getDragOrigin()));
- event.startDrag(DragSource.DefaultLinkDrop, MidiCablePane.dragging, new DragSourceAdapter() {
+ protected Transferable createTransferable(JComponent compo) {
+ cablePane.setDragSourceTransceiver(getSelectedValue());
+ return new Transferable() {
+ @Override
+ public Object getTransferData(DataFlavor flavor) {
+ return cablePane.getDragSourceTransceiver();
+ }
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return (DataFlavor[]) flavors.toArray();
+ }
@Override
- public void dragDropEnd(DragSourceDropEvent event) {
- Transmitter tx = (Transmitter)MidiCablePane.dragging.getData();
- if( ! event.getDropSuccess() ) {
- getModel().closeTransmitter(tx);
- } else if( tx instanceof DummyTransmitter ) {
- Receiver rx = tx.getReceiver();
- tx.close();
- try {
- getModel().openTransmitter().setReceiver(rx);
- } catch (Exception exception) {
- exception.printStackTrace();
- }
- }
- cablePane.updateDraggingLocation(null);
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return flavors.contains(flavor);
}
- });
+ };
}
- };
- dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
- dragSource.addDragSourceMotionListener(new DragSourceMotionListener() {
@Override
- public void dragMouseMoved(DragSourceDragEvent dsde) {
- cablePane.updateDraggingLocation(dsde.getLocation());
+ protected void exportDone(JComponent source, Transferable data, int action) {
+ try {
+ Transmitter tx = (Transmitter) data.getTransferData(elementFlavor);
+ if( action == NONE ) {
+ getModel().closeTransmitter(tx);
+ }
+ else if( tx instanceof DummyTransmitter ) {
+ Receiver rx = tx.getReceiver();
+ tx.close();
+ getModel().openTransmitter().setReceiver(rx);
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ cablePane.setDragSourceTransceiver(null);
}
- });
- }
- /**
- * {@link Receiver}のドロップを受け付けます。
- */
- private void setupDrop() {
- DropTargetListener dtl = new DropTargetAdapter() {
@Override
- public void dragEnter(DropTargetDragEvent event) {
- if( event.isDataFlavorSupported(DraggingTransceiver.receiverFlavor) ) {
- event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
+ public boolean canImport(TransferSupport support) {
+ if( ! support.isDrop() ) return false;
+ if( support.isDataFlavorSupported(ReceiverListView.elementFlavor) ) {
+ Transmitter to = getElementAt(support.getDropLocation().getDropPoint());
+ cablePane.setDragDestinationTransceiver(to);
+ return true;
}
+ cablePane.setDragDestinationTransceiver(null);
+ return false;
}
@Override
- public void drop(DropTargetDropEvent event) {
- event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
- if( (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) {
- event.dropComplete(false);
- return;
- }
- Transferable t = event.getTransferable();
- if( ! t.isDataFlavorSupported(DraggingTransceiver.receiverFlavor) ) {
- event.dropComplete(false);
- return;
- }
+ public boolean importData(TransferSupport support) {
try {
- Object rx = t.getTransferData(DraggingTransceiver.receiverFlavor);
- if( rx != null ) {
- Transmitter tx = getElementAt(event.getLocation());
- if( tx instanceof DummyTransmitter ) tx = getModel().openTransmitter();
- tx.setReceiver((Receiver)rx);
- event.dropComplete(true);
- return;
- }
- }
- catch (Exception ex) {
- ex.printStackTrace();
+ Object from = support.getTransferable().getTransferData(ReceiverListView.elementFlavor);
+ if( ! (from instanceof Receiver) ) return false;
+ Transmitter to = getElementAt(support.getDropLocation().getDropPoint());
+ if( to instanceof DummyTransmitter ) to = getModel().openTransmitter();
+ to.setReceiver((Receiver)from);
+ return true;
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ return false;
}
- event.dropComplete(false);
}
- };
- new DropTarget( this, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true );
+ });
}
}
import java.awt.FlowLayout;
import java.awt.Insets;
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.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
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.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
}
/**
- * ã\83\89ã\83ã\83\83ã\83\97ã\81\95ã\82\8cã\81\9fè¤\87æ\95°ã\81®MIDIã\83\95ã\82¡ã\82¤ã\83«ã\82\92èªã\81¿è¾¼ã\82\80ã\83ªã\82¹ã\83\8aー
+ * ã\83\89ã\83ã\83\83ã\83\97ã\81\95ã\82\8cã\81\9fè¤\87æ\95°ã\81®MIDIã\83\95ã\82¡ã\82¤ã\83«ã\82\92èªã\81¿è¾¼ã\82\80ã\83\8fã\83³ã\83\89ã\83©ー
*/
- public final DropTargetListener dropTargetListener = new DropTargetAdapter() {
+ public final TransferHandler transferHandler = new TransferHandler() {
@Override
- public void dragEnter(DropTargetDragEvent event) {
- if( event.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ) {
- event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
- }
+ public boolean canImport(TransferSupport support) {
+ return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
}
- @Override
@SuppressWarnings("unchecked")
- public void drop(DropTargetDropEvent event) {
- event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+ @Override
+ public boolean importData(TransferSupport support) {
try {
- if ( (event.getDropAction() & 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();
+ loadAndPlay((List<File>)support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
}
- event.dropComplete(false);
}
};
setTitle("MIDI Editor/Playlist - MIDI Chord Helper");
setBounds( 150, 200, 900, 500 );
setLayout(new FlowLayout());
- new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetListener, true);
+ setTransferHandler(transferHandler);
//
// パネルレイアウト
JPanel playlistPanel = new JPanel() {{