OSDN Git Service

2e17dc058fd6c3fa3d5961b489774181040c6c29
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / midieditor / Base64Dialog.java
1 package camidion.chordhelper.midieditor;
2 import java.awt.Dimension;
3 import java.awt.event.ActionEvent;
4 import java.io.ByteArrayInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.util.Base64;
8 import java.util.regex.Pattern;
9
10 import javax.sound.midi.InvalidMidiDataException;
11 import javax.sound.midi.MidiSystem;
12 import javax.swing.AbstractAction;
13 import javax.swing.Action;
14 import javax.swing.Box;
15 import javax.swing.BoxLayout;
16 import javax.swing.JButton;
17 import javax.swing.JDialog;
18 import javax.swing.JOptionPane;
19 import javax.swing.JPanel;
20 import javax.swing.JScrollPane;
21 import javax.swing.JTextArea;
22 import javax.swing.event.DocumentEvent;
23 import javax.swing.event.DocumentListener;
24
25 import camidion.chordhelper.ButtonIcon;
26 import camidion.chordhelper.ChordHelperApplet;
27
28 /**
29  * Base64テキスト入力ダイアログ
30  */
31 public class Base64Dialog extends JDialog implements DocumentListener {
32         public static final Pattern HEADER_PATTERN = Pattern.compile("^.*:.*$", Pattern.MULTILINE);
33         private JTextArea base64TextArea = new JTextArea(8,56);
34         private void error(String message) {
35                 JOptionPane.showMessageDialog(base64TextArea, (Object)message,
36                                 ChordHelperApplet.VersionInfo.NAME, JOptionPane.WARNING_MESSAGE);
37                 base64TextArea.requestFocusInWindow();
38         }
39         private String createHeader(String filename) {
40                 return "Content-Type: audio/midi; name=\"" + filename + "\"\n"
41                                 + "Content-Transfer-Encoding: base64\n\n";
42         }
43         public PlaylistTable playlistTable;
44         /**
45          * 入力されたBase64テキストをデコードし、MIDIシーケンスとしてプレイリストに追加します。
46          * @return プレイリストに追加されたMIDIシーケンスのインデックス(先頭が0)、追加に失敗した場合は -1
47          */
48         public int addToPlaylist() {
49                 byte[] midiData = null;
50                 try {
51                         midiData = getMIDIData();
52                 } catch(Exception e) {
53                         error("Base64デコードに失敗しました。\n"+e);
54                         return -1;
55                 }
56                 try (InputStream in = new ByteArrayInputStream(midiData)) {
57                         int index = playlistTable.getModel().add(MidiSystem.getSequence(in), null);
58                         playlistTable.getSelectionModel().setSelectionInterval(index, index);
59                         return index;
60                 } catch( IOException|InvalidMidiDataException e ) {
61                         error("Base64デコードした結果をMIDIシーケンスとして読み込めませんでした。\n"+e);
62                         return -1;
63                 }
64         }
65         /**
66          * Base64デコードアクション
67          */
68         public Action addBase64Action = new AbstractAction("Add to PlayList", new ButtonIcon(ButtonIcon.EJECT_ICON)) {
69                 { putValue(Action.SHORT_DESCRIPTION, "Base64デコードして、プレイリストへ追加"); }
70                 @Override
71                 public void actionPerformed(ActionEvent e) {
72                         if( addToPlaylist() >= 0 ) setVisible(false);
73                 }
74         };
75         /**
76          * Base64テキストクリアアクション
77          */
78         public Action clearAction = new AbstractAction("Clear", new ButtonIcon(ButtonIcon.X_ICON)) {
79                 { putValue(Action.SHORT_DESCRIPTION, "Base64テキスト欄を消去"); }
80                 @Override
81                 public void actionPerformed(ActionEvent e) { setText(null); }
82         };
83         /**
84          * Base64テキスト入力ダイアログを構築します。
85          * @param playlistTable Base64デコードされたMIDIシーケンスの追加先プレイリストビュー
86          */
87         public Base64Dialog(PlaylistTable playlistTable) {
88                 this.playlistTable = playlistTable;
89                 setTitle("Base64-encoded MIDI sequence - " + ChordHelperApplet.VersionInfo.NAME);
90                 add(new JPanel() {{
91                         setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
92                         add(new JPanel() {{
93                                 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
94                                 add(Box.createRigidArea(new Dimension(10, 0)));
95                                 add(new JButton(addBase64Action){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
96                                 add(new JButton(clearAction){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
97                         }});
98                         add(new JScrollPane(base64TextArea));
99                 }});
100                 setBounds( 300, 250, 660, 300 );
101                 base64TextArea.setToolTipText("Paste Base64-encoded MIDI sequence here");
102                 base64TextArea.getDocument().addDocumentListener(this);
103                 addBase64Action.setEnabled(false);
104                 clearAction.setEnabled(false);
105         }
106         @Override
107         public void insertUpdate(DocumentEvent e) {
108                 addBase64Action.setEnabled(true);
109                 clearAction.setEnabled(true);
110         }
111         @Override
112         public void removeUpdate(DocumentEvent e) {
113                 if( e.getDocument().getLength() > 0 ) return;
114                 addBase64Action.setEnabled(false);
115                 clearAction.setEnabled(false);
116         }
117         @Override
118         public void changedUpdate(DocumentEvent e) { }
119         /**
120          * バイナリー形式でMIDIデータを返します。
121          * @return バイナリー形式のMIDIデータ
122          * @throws IllegalArgumentException 入力されているテキストが有効なBase64スキームになっていない場合
123          */
124         public byte[] getMIDIData() {
125                 String body = HEADER_PATTERN.matcher(base64TextArea.getText()).replaceAll("");
126                 return Base64.getMimeDecoder().decode(body.getBytes());
127         }
128         /**
129          * バイナリー形式のMIDIデータを設定します。
130          * @param midiData バイナリー形式のMIDIデータ
131          */
132         public void setMIDIData(byte[] midiData) { setMIDIData(midiData, null); }
133         /**
134          * バイナリー形式のMIDIデータを、ファイル名をつけて設定します。
135          * @param midiData バイナリー形式のMIDIデータ
136          * @param filename ファイル名
137          */
138         public void setMIDIData(byte[] midiData, String filename) {
139                 if( midiData == null || midiData.length == 0 ) return;
140                 if( filename == null ) filename = "";
141                 setText(createHeader(filename) + Base64.getMimeEncoder().encodeToString(midiData) + "\n");
142                 base64TextArea.selectAll();
143         }
144         /**
145          * Base64形式でMIDIデータを返します。
146          * @return  Base64形式のMIDIデータ
147          */
148         public String getBase64Data() { return base64TextArea.getText(); }
149         /**
150          * Base64形式のMIDIデータを設定します。
151          * @param base64Data Base64形式のMIDIデータ
152          */
153         public void setBase64Data(String base64Data) {
154                 setText(null);
155                 base64TextArea.append(base64Data);
156         }
157         /**
158          * Base64形式のMIDIデータを、ファイル名をつけて設定します。
159          * @param base64Data Base64形式のMIDIデータ
160          * @param filename ファイル名
161          */
162         public void setBase64Data(String base64Data, String filename) {
163                 setText(createHeader(filename));
164                 base64TextArea.append(base64Data);
165         }
166         /**
167          * テキスト文字列を設定します。
168          * @param text テキスト文字列
169          */
170         public void setText(String text) { base64TextArea.setText(text); }
171 }