OSDN Git Service

リファクタリング(MIDIデバイス周り)
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / mididevice / ReceiverListView.java
1 package camidion.chordhelper.mididevice;
2
3 import java.awt.Component;
4 import java.awt.Rectangle;
5 import java.awt.datatransfer.Transferable;
6 import java.awt.dnd.DnDConstants;
7 import java.awt.dnd.DragGestureEvent;
8 import java.awt.dnd.DragGestureListener;
9 import java.awt.dnd.DragSource;
10 import java.awt.dnd.DropTarget;
11 import java.awt.dnd.DropTargetAdapter;
12 import java.awt.dnd.DropTargetDragEvent;
13 import java.awt.dnd.DropTargetDropEvent;
14 import java.awt.dnd.DropTargetListener;
15
16 import javax.sound.midi.Receiver;
17 import javax.sound.midi.Transmitter;
18 import javax.swing.JLabel;
19 import javax.swing.JList;
20 import javax.swing.ListCellRenderer;
21 import javax.swing.ListSelectionModel;
22
23 /**
24  * MIDIレシーバ({@link Receiver})のリストビューです。
25  * レシーバをこのビューからドラッグし、
26  * {@link TransmitterListView} のトランスミッタにドロップして接続できます。
27  */
28 public class ReceiverListView extends JList<Receiver> {
29         /**
30          * レシーバを描画するクラス
31          */
32         private static class CellRenderer extends JLabel implements ListCellRenderer<Receiver> {
33                 public Component getListCellRendererComponent(JList<? extends Receiver> list,
34                                 Receiver value, int index, boolean isSelected, boolean cellHasFocus)
35                 {
36                         setEnabled(list.isEnabled());
37                         setFont(list.getFont());
38                         setOpaque(true);
39                         if (isSelected) {
40                                 setBackground(list.getSelectionBackground());
41                                 setForeground(list.getSelectionForeground());
42                         } else {
43                                 setBackground(list.getBackground());
44                                 setForeground(list.getForeground());
45                         }
46                         setIcon(MidiDeviceDialog.MIDI_CONNECTER_ICON);
47                         setToolTipText("受信端子(Rx):ドラッグ&ドロップしてTxに接続できます。");
48                         return this;
49                 }
50         }
51         /**
52          * 引数で指定された{@link Receiver}のセル範囲を示す、
53          * リストの座標系内の境界の矩形を返します。対応するセルがない場合はnullを返します。
54          * @return セル範囲を示す境界の矩形、またはnull
55          */
56         public Rectangle getCellBounds(Receiver rx) {
57                 int index = getModel().indexOf(rx);
58                 return getCellBounds(index,index);
59         }
60         /**
61          * このリストによって表示される{@link Receiver}のリストを保持するデータモデルを返します。
62          * @return 表示される{@link Receiver}のリストを提供するデータモデル
63          */
64         @Override
65         public ReceiverListModel getModel() {
66                 return (ReceiverListModel) super.getModel();
67         }
68         /**
69          * 仮想MIDI端子リストビューを生成します。
70          * @param model このビューから参照されるデータモデル
71          * @param cablePane MIDIケーブル描画面
72          */
73         public ReceiverListView(ReceiverListModel model, MidiCablePane cablePane) {
74                 super(model);
75                 setCellRenderer(new CellRenderer());
76                 setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
77                 setLayoutOrientation(JList.HORIZONTAL_WRAP);
78                 setVisibleRowCount(0);
79                 //
80                 // レシーバのドラッグを受け付ける
81                 DragGestureListener dgl = new DragGestureListener() {
82                         @Override
83                         public void dragGestureRecognized(DragGestureEvent event) {
84                                 if( (event.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) return;
85                                 MidiCablePane.dragging.setData(getModel().getElementAt(locationToIndex(event.getDragOrigin())));
86                                 event.startDrag(DragSource.DefaultLinkDrop, MidiCablePane.dragging, cablePane.dragSourceListener);
87                         }
88                 };
89                 DragSource dragSource = new DragSource();
90                 dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
91                 dragSource.addDragSourceMotionListener(cablePane.dragSourceMotionListener);
92                 //
93                 // 外からドラッグされたトランスミッタを、ドロップした場所のレシーバに接続する
94                 DropTargetListener dtl = new DropTargetAdapter() {
95                         @Override
96                         public void dragEnter(DropTargetDragEvent event) {
97                                 if( event.isDataFlavorSupported(DraggingTransceiver.transmitterFlavor) ) {
98                                         event.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
99                                 }
100                         }
101                         @Override
102                         public void drop(DropTargetDropEvent event) {
103                                 event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
104                                 int maskedBits = event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE;
105                                 if( maskedBits == 0 ) {
106                                         event.dropComplete(false);
107                                         return;
108                                 }
109                                 Transferable t = event.getTransferable();
110                                 if( ! t.isDataFlavorSupported(DraggingTransceiver.transmitterFlavor) ) {
111                                         event.dropComplete(false);
112                                         return;
113                                 }
114                                 try {
115                                         Object tx = t.getTransferData(DraggingTransceiver.transmitterFlavor);
116                                         if( tx != null ) {
117                                                 ((Transmitter)tx).setReceiver(getModel().getElementAt(locationToIndex(event.getLocation())));
118                                                 event.dropComplete(true);
119                                                 return;
120                                         }
121                                 }
122                                 catch (Exception ex) {
123                                         ex.printStackTrace();
124                                 }
125                                 event.dropComplete(false);
126                         }
127                 };
128                 new DropTarget( this, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true );
129         }
130 }