package camidion.chordhelper.mididevice;
+import java.awt.BorderLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
import javax.sound.midi.MidiDevice;
-import javax.swing.BoxLayout;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Transmitter;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
-import javax.swing.event.InternalFrameAdapter;
-import javax.swing.event.InternalFrameEvent;
/**
* MIDIデバイスフレームビュー
*/
public class MidiDeviceFrame extends JInternalFrame {
+ private MidiDeviceModel deviceModel;
+ private TransmitterListView transmitterListView;
+ private ReceiverListView receiverListView;
+ private JScrollPane scrollPane;
+ private JPanel trxPanel, txPanel, rxPanel;
+ private Timer timer;
/**
- * デバイスの仮想MIDI端子リストビュー
+ * このデバイスフレームに表示内容を提供しているMIDIデバイスモデルを取得します。
+ * @return MIDIデバイスモデル
*/
- MidiConnecterListView listView;
+ public MidiDeviceModel getMidiDeviceModel() { return deviceModel; }
/**
- * デバイスのタイムスタンプを更新するタイマー
+ * このデバイスフレームに貼り付けられたMIDIトランスミッタリストビューを取得します。
+ * @return MIDIトランスミッタリストビュー
*/
- Timer timer;
+ public TransmitterListView getMidiTransmitterListView() { return transmitterListView; }
/**
- * MIDIデバイスのモデルからフレームビューを構築します。
- * @param model MIDIデバイスのTransmitter/Receiverリストモデル
+ * このデバイスフレームに貼り付けられたMIDIトランシーバリストビューを取得します。
+ * @return MIDIトランシーバリストビュー
*/
- public MidiDeviceFrame(MidiConnecterListModel model) {
+ public ReceiverListView getMidiReceiverListView() { return receiverListView; }
+ /**
+ * ダイアログウィンドウがアクティブなときだけタイムスタンプ更新を有効にするためのリスナー
+ */
+ public final WindowListener windowListener = new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) { timer.stop(); }
+ @Override
+ public void windowActivated(WindowEvent e) { timer.start(); }
+ };
+ /**
+ * MIDIデバイスモデルからフレームビューを構築します。
+ */
+ public MidiDeviceFrame(MidiDeviceModel deviceModel, MidiCablePane cablePane) {
super( null, true, true, false, false );
- //
- // タイトルの設定
- String title = model.toString();
- if( model.txSupported() ) {
- title = (model.rxSupported()?"[I/O] ":"[IN] ")+title;
- }
- else {
- title = (model.rxSupported()?"[OUT] ":"[No I/O] ")+title;
- }
- setTitle(title);
- listView = new MidiConnecterListView(model);
+ this.deviceModel = deviceModel;
+ setTitle("[" + deviceModel.getMidiDeviceInOutType().getShortName() + "] " + deviceModel);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
- addInternalFrameListener(
- new InternalFrameAdapter() {
- public void internalFrameOpened(InternalFrameEvent e) {
- if( ! listView.getModel().getMidiDevice().isOpen() )
- setVisible(false);
- }
- public void internalFrameClosing(InternalFrameEvent e) {
- MidiConnecterListModel m = listView.getModel();
- m.closeDevice();
- if( ! m.getMidiDevice().isOpen() )
- setVisible(false);
+ setLayout(new BorderLayout());
+ add(new JLabel("--:--") {{
+ timer = new Timer(50, new ActionListener() {
+ private long sec = -2;
+ private MidiDevice device = getMidiDeviceModel().getMidiDevice();
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ long usec = device.getMicrosecondPosition();
+ long sec = (usec == -1 ? -1 : usec/1000000);
+ if( sec == this.sec ) return;
+ this.sec = sec;
+ setText(sec == -1?"--:--":String.format("%02d:%02d",sec/60,sec%60));
+ cablePane.repaint();
}
+ });
+ }}, BorderLayout.SOUTH);
+ add(scrollPane = new JScrollPane(trxPanel = new JPanel() {{
+ setLayout(new BorderLayout());
+ ReceiverListModel rxListModel = getMidiDeviceModel().getReceiverListModel();
+ if( rxListModel != null ) {
+ receiverListView = new ReceiverListView(rxListModel, cablePane);
+ add(rxPanel = new JPanel() {{
+ setLayout(new BorderLayout());
+ add(new JLabel("Rx") {{ setVerticalAlignment(TOP); }}, BorderLayout.WEST);
+ add(receiverListView);
+ }}, BorderLayout.NORTH);
+ }
+ TransmitterListModel txListModel = getMidiDeviceModel().getTransmitterListModel();
+ if( txListModel != null ) {
+ transmitterListView = new TransmitterListView(txListModel, cablePane);
+ add(txPanel = new JPanel() {{
+ setLayout(new BorderLayout());
+ add(new JLabel("Tx") {{ setVerticalAlignment(TOP); }}, BorderLayout.WEST);
+ add(transmitterListView);
+ }}, rxListModel == null ? BorderLayout.NORTH : BorderLayout.SOUTH);
}
- );
- setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
- add(new JScrollPane(listView));
- add(new JPanel() {{
- add(new JLabel() {{
- timer = new Timer(50, new ActionListener() {
- private long sec = -2;
- private MidiDevice dev = listView.getModel().getMidiDevice();
- @Override
- public void actionPerformed(ActionEvent e) {
- long usec = dev.getMicrosecondPosition();
- long sec = (usec == -1 ? -1 : usec/1000000);
- if( sec == this.sec ) return;
- String text;
- if( (this.sec = sec) == -1 )
- text = "No TimeStamp";
- else
- text = String.format("TimeStamp: %02d:%02d", sec/60, sec%60);
- setText(text);
- }
- });
- }});
- }});
+ }}));
}
/**
- * 指定されたインデックスが示す仮想MIDI端子リストの要素のセル範囲を返します。
- *
- * @param index リスト要素のインデックス
- * @return セル範囲の矩形
+ * 引数で指定された{@link Transmitter}のセル範囲を示す、
+ * デスクトップの座標系内の境界の矩形を返します。対応するセルがない場合はnullを返します。
+ * @return セル範囲を示す境界の矩形、またはnull
*/
- public Rectangle getListCellBounds(int index) {
- Rectangle rect = listView.getCellBounds(index,index);
- if( rect == null )
- return null;
- rect.translate(
- getRootPane().getX() + getContentPane().getX(),
- getRootPane().getY() + getContentPane().getY()
- );
+ 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;
}
/**
- * 仮想MIDI端子リストの指定された要素のセル範囲を返します。
- *
- * @param transciver 要素となるMIDI端子(Transmitter または Receiver)
- * @return セル範囲の矩形
+ * 引数で指定された{@link Receiver}のセル範囲を示す、
+ * デスクトップの座標系内の境界の矩形を返します。対応するセルがない場合はnullを返します。
+ * @return セル範囲を示す境界の矩形、またはnull
*/
- public Rectangle getListCellBounds(AutoCloseable transciver) {
- return getListCellBounds(listView.getModel().indexOf(transciver));
+ 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, AbstractTransceiverListView<?> list) {
+ int x = getX() + getRootPane().getX() + getContentPane().getX() +
+ scrollPane.getX() + trxPanel.getX() +
+ panel.getX() + list.getX();
+ int y = getY() + getRootPane().getY() + getContentPane().getY() +
+ scrollPane.getY() + trxPanel.getY() +
+ panel.getY() + list.getY();
+ rect.translate(x,y);
}
-}
\ No newline at end of file
+}