3 import java.awt.event.*;
4 import javax.sound.midi.*;
9 * A generator class for the application's dialogs.
11 * @author Björn Lanneskog
14 public class MooDialog extends JDialog {
16 private JLabel labelA, labelB, labelC, labelD, labelE, labelF;
17 private JTextField textFieldA, textFieldB, textFieldC, textFieldD, textFieldE, textFieldF;
18 private JTextField textFieldG, textFieldH, textFieldI, textFieldJ, textFieldK;
19 private JComboBox trackListA, trackListB;
20 private JButton okButton, cancelButton;
21 public static final int ADD_TRACK = 1,
33 * Constructor of the dialogs.
35 public MooDialog(int type) {
36 super(Moosique.getGUI(), false);
38 Container pane = getContentPane();
41 Track[] tracks = Moosique.getSequence().getTracks();
44 case ADD_TRACK: makeAddDialog(pane, tracks); break;
45 case DELETE_TRACK: makeDelDialog(pane, tracks); break;
46 case COPY_TRACK: makeCopyDialog(pane, tracks); break;
47 case MOVE_TRACK: makeMoveDialog(pane, tracks); break;
48 case SET_POSITION: makeSetPositionDialog(pane); break;
49 case MANUAL: makeTextDialog(pane, "Manual.txt"); break;
50 case INSERT_MEASURE: makeInsertMeasureDialog(pane); break;
51 case DELETE_MEASURE: makeDeleteMeasureDialog(pane); break;
52 case SET_TEMPO: makeSetTempoDialog(pane); break;
53 case PREFERENCES: makePrefsDialog(pane); break;
58 * Builds the add track popupdialog.
59 * @param pane The container to put the dialog in.
60 * @param tracks A array containing miditracks.
62 private void makeAddDialog(Container pane, Track[] tracks) {
64 setTitle("Add track");
65 labelA = new JLabel("Name of track", JLabel.CENTER);
67 textFieldA = new JTextField();
69 labelB = new JLabel("Add after", JLabel.CENTER);
71 trackListA = new JComboBox();
72 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
74 cancelButton = new JButton("Cancel");
75 pane.add(cancelButton);
76 okButton = new JButton("OK");
79 labelA.setBounds(50, 10, 100, 20);
80 textFieldA.setBounds(40, 35, 120, 20);
81 labelB.setBounds(50, 70, 100, 20);
82 trackListA.setBounds(40, 95, 120, 20);
83 cancelButton.setBounds(10, 150, 80, 30);
84 okButton.setBounds(120, 150, 60, 30);
89 setLocationRelativeTo(Moosique.getGUI());
94 * Builds the delete track popupdialog.
95 * @param pane The container to put the dialog in.
96 * @param tracks A array containing miditracks.
98 private void makeDelDialog(Container pane, Track[] tracks) {
100 setTitle("Delete track");
101 labelB = new JLabel("Delete track", JLabel.CENTER);
103 trackListA = new JComboBox();
104 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
105 pane.add(trackListA);
106 cancelButton = new JButton("Cancel");
107 pane.add(cancelButton);
108 okButton = new JButton("OK");
111 labelB.setBounds(50, 10, 100, 20);
112 trackListA.setBounds(40, 35, 120, 20);
113 cancelButton.setBounds(10, 90, 80, 30);
114 okButton.setBounds(120, 90, 60, 30);
119 setLocationRelativeTo(Moosique.getGUI());
124 * Builds the copy track popupdialog.
125 * @param pane The container to put the dialog in.
126 * @param tracks A array containing miditracks.
128 private void makeCopyDialog(Container pane, Track[] tracks) {
130 setTitle("Copy Track");
131 labelA = new JLabel("Track to copy", JLabel.CENTER);
133 trackListA = new JComboBox();
134 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
135 pane.add(trackListA);
136 labelB = new JLabel("Insert after", JLabel.CENTER);
138 trackListB = new JComboBox();
139 for (int i = 1; i <= tracks.length; i++) trackListB.addItem("Track " + i);
140 pane.add(trackListB);
141 cancelButton = new JButton("Cancel");
142 pane.add(cancelButton);
143 okButton = new JButton("OK");
146 labelA.setBounds(50, 10, 100, 20);
147 trackListA.setBounds(40, 35, 120, 20);
148 labelB.setBounds(50, 70, 100, 20);
149 trackListB.setBounds(40, 95, 120, 20);
150 cancelButton.setBounds(10, 150, 80, 30);
151 okButton.setBounds(120, 150, 60, 30);
156 setLocationRelativeTo(Moosique.getGUI());
161 * Builds the move track popupdialog
162 * @param pane The container to put the dialog in.
163 * @param tracks A array containing miditracks.
165 private void makeMoveDialog(Container pane, Track[] tracks) {
167 setTitle("Move track");
168 labelA = new JLabel("Track to move", JLabel.CENTER);
170 trackListA = new JComboBox();
171 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
172 pane.add(trackListA);
173 labelB = new JLabel("Insert after", JLabel.CENTER);
175 trackListB = new JComboBox();
176 for (int i = 1; i <= tracks.length; i++) trackListB.addItem("Track " + i);
177 pane.add(trackListB);
178 cancelButton = new JButton("Cancel");
179 pane.add(cancelButton);
180 okButton = new JButton("OK");
183 labelA.setBounds(40, 10, 120, 20);
184 trackListA.setBounds(40, 35, 120, 20);
185 labelB.setBounds(50, 70, 100, 20);
186 trackListB.setBounds(40, 95, 120, 20);
187 cancelButton.setBounds(10, 150, 80, 30);
188 okButton.setBounds(120, 150, 60, 30);
193 setLocationRelativeTo(Moosique.getGUI());
198 * Builds the set position dialog.
199 * @param pane The container to put the dialog in.
200 * @param tracks A array containing miditracks.
202 private void makeSetPositionDialog(Container pane) {
204 setTitle("Set edit position");
205 labelA = new JLabel("Measure", JLabel.CENTER);
207 labelB = new JLabel("Beat", JLabel.CENTER);
209 labelC = new JLabel("Tick", JLabel.CENTER);
211 textFieldA = new JTextField();
212 pane.add(textFieldA);
213 textFieldB = new JTextField();
214 pane.add(textFieldB);
215 textFieldC = new JTextField();
216 pane.add(textFieldC);
217 cancelButton = new JButton("Cancel");
218 pane.add(cancelButton);
219 okButton = new JButton("OK");
222 labelA.setBounds(40, 25, 50, 20);
223 labelB.setBounds(105, 25, 50, 20);
224 labelC.setBounds(170, 25, 50, 20);
225 textFieldA.setBounds(40, 45, 50, 20);
226 textFieldB.setBounds(105, 45, 50, 20);
227 textFieldC.setBounds(170, 45, 50, 20);
228 cancelButton.setBounds(35, 90, 80, 30);
229 okButton.setBounds(155, 90, 60, 30);
234 setLocationRelativeTo(Moosique.getGUI());
239 * Builds the insert measure popupdialog.
240 * @param pane The container to put the dialog in.
242 private void makeInsertMeasureDialog(Container pane){
244 setTitle("Insert Measure");
245 labelA = new JLabel("Insert at:", JLabel.RIGHT);
247 labelB = new JLabel("Measure count:", JLabel.RIGHT);
249 textFieldA = new JTextField();
250 pane.add(textFieldA);
251 textFieldB = new JTextField();
252 pane.add(textFieldB);
253 cancelButton = new JButton("Cancel");
254 pane.add(cancelButton);
255 okButton = new JButton("OK");
258 labelA.setBounds(20, 20, 110 ,20);
259 labelB.setBounds(20, 50, 110, 20);
260 textFieldA.setBounds(140 ,20 , 40, 20);
261 textFieldB.setBounds(140,50, 40, 20);
262 cancelButton.setBounds(20 ,95 , 80, 30);
263 okButton.setBounds(120, 95, 60, 30);
268 setLocationRelativeTo(Moosique.getGUI());
273 * Builds the delete measure popupdialog.
274 * @param pane The container to put the dialog in.
276 private void makeDeleteMeasureDialog(Container pane) {
278 setTitle("Delete Measure");
279 labelA = new JLabel("Delete at:", JLabel.RIGHT);
281 labelB = new JLabel("Measure count:", JLabel.RIGHT);
283 textFieldA = new JTextField();
284 pane.add(textFieldA);
285 textFieldB = new JTextField();
286 pane.add(textFieldB);
287 cancelButton = new JButton("Cancel");
288 pane.add(cancelButton);
289 okButton = new JButton("OK");
292 labelA.setBounds(20, 20, 110 ,20);
293 labelB.setBounds(20, 50, 110, 20);
294 textFieldA.setBounds(140 ,20 , 40, 20);
295 textFieldB.setBounds(140,50, 40, 20);
296 cancelButton.setBounds(20 ,95 , 80, 30);
297 okButton.setBounds(120, 95, 60, 30);
302 setLocationRelativeTo(Moosique.getGUI());
307 * Builds the set tempo dialog.
308 * @param pane The container to put the dialog in.
309 * @param tracks A array containing miditracks.
311 private void makeSetTempoDialog(Container pane) {
313 setTitle("Set tempo");
314 // creating labels and adding them to a container
315 labelA = new JLabel("Measure", JLabel.CENTER);
317 labelB = new JLabel("Beat", JLabel.CENTER);
319 labelC = new JLabel("Tick", JLabel.CENTER);
321 labelD = new JLabel("Start at:", JLabel.RIGHT);
323 labelE = new JLabel("End at:", JLabel.RIGHT);
325 labelF = new JLabel("to", JLabel.CENTER);
328 // the starting textfields and adding them to the container
329 textFieldA = new JTextField();
330 pane.add(textFieldA);
331 textFieldB = new JTextField();
332 pane.add(textFieldB);
333 textFieldC = new JTextField();
334 pane.add(textFieldC);
335 // ending textfields and adding them to the container
336 textFieldD = new JTextField();
337 pane.add(textFieldD);
338 textFieldE = new JTextField();
339 pane.add(textFieldE);
340 textFieldF = new JTextField();
341 pane.add(textFieldF);
342 // the amount to edit textfields and adding them to a container
343 textFieldG = new JTextField();
344 pane.add(textFieldG);
345 textFieldH = new JTextField();
346 pane.add(textFieldH);
347 textFieldI = new JTextField();
348 pane.add(textFieldI);
349 textFieldJ = new JTextField();
350 pane.add(textFieldJ);
351 textFieldK = new JTextField();
352 pane.add(textFieldK);
354 // creating the buttons and adding them to the container
355 JRadioButton constant = new JRadioButton("Set constant tempo of:");
356 constant.setSelected(true);
358 JRadioButton change = new JRadioButton("Gradually change tempo:");
360 JRadioButton scale = new JRadioButton("Scale tempo in %:");
362 JRadioButton add = new JRadioButton("Add to current tempo:");
365 // creating a buttongroup and adding the buttons above
366 ButtonGroup group = new ButtonGroup();
372 // creating the cancel and ok button
373 cancelButton = new JButton("Cancel");
374 pane.add(cancelButton);
375 okButton = new JButton("OK");
379 labelA.setBounds(80, 25, 50, 20);
380 labelB.setBounds(145, 25, 50, 20);
381 labelC.setBounds(210, 25, 50, 20);
382 labelD.setBounds(20, 45, 60, 20);
383 labelE.setBounds(20, 65, 60, 20);
384 labelF.setBounds(255, 125, 20 ,20);
386 textFieldA.setBounds(80, 45, 50, 20);
387 textFieldB.setBounds(145, 45, 50, 20);
388 textFieldC.setBounds(210, 45, 50, 20);
389 textFieldD.setBounds(80, 65, 50, 20);
390 textFieldE.setBounds(145, 65, 50, 20);
391 textFieldF.setBounds(210, 65, 50, 20);
393 textFieldG.setBounds(205, 100, 35, 20);
394 textFieldH.setBounds(220, 125, 35, 20);
395 textFieldI.setBounds(280, 125, 35, 20);
396 textFieldJ.setBounds(170, 150, 35, 20);
397 textFieldK.setBounds(200, 175, 35, 20);
399 constant.setBounds(20, 100, 180, 20);
400 change.setBounds(20, 125, 200, 20);
401 scale.setBounds(20, 150, 150, 20);
402 add.setBounds(20, 175, 175, 20);
404 cancelButton.setBounds(75, 215, 80, 30);
405 okButton.setBounds(195, 215, 60, 30);
410 setLocationRelativeTo(Moosique.getGUI());
415 private void makeTextDialog(Container pane, String filename) {
416 setTitle("User Manual");
417 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
418 File manual = new File(filename);
421 BufferedReader br = new BufferedReader(new FileReader(manual));
422 char[] chars = new char[(int)manual.length()];
423 br.read(chars, 0, (int)manual.length());
424 s = new String(chars);
425 } catch (Exception ex) {
426 s = "Manual not found";
428 pane.add(new JScrollPane(new JTextArea(s, 30, 95)));
429 Action close = new AbstractAction("Close") {
430 public void actionPerformed(ActionEvent ae) {
433 JButton closeButton = new JButton(close);
434 closeButton.setAlignmentX(Component.CENTER_ALIGNMENT);
435 pane.add(closeButton);
438 setLocationRelativeTo(Moosique.getGUI());
442 private void makePrefsDialog(Container pane) {
444 MidiDevice.Info[] devInfo = MidiSystem.getMidiDeviceInfo();
445 for (int i = 0; i < devInfo.length; i++) {
446 if (MidiSystem.getMidiDevice(devInfo[i]) instanceof Sequencer) {
448 } else if (MidiSystem.getMidiDevice(devInfo[i]) instanceof Synthesizer) {
452 String[] seqNames, synthNames;
453 JPanel pane = (JPanel) this.getContentPane();
454 pane.add(new JLabel("Sequencer"));
455 JComboBox seqBox = new JComboBox(seqNames);
456 pane.add(new JLabel("Synthesizer"));
457 JComboBox synthBox = new JComboBox(synthNames);
461 private MooNote note;
462 private JOptionPane optionPane;
463 private JTextField pitch;
464 private JTextField velocity;
465 private JTextField length;
468 * Creates a new note preference dialog.
469 * @param mn the note that will be graphically represented
471 public MooDialog(MooNote mn) {
472 super(Moosique.getGUI(), "Note properties", false);
474 pitch = new JTextField(new Integer(note.getPitch()).toString(),3);
475 JPanel pitchpanel = new JPanel();
476 pitchpanel.add(new Label("Pitch: "));
477 pitchpanel.add(pitch);
479 velocity = new JTextField(new Integer(note.getVelocity()).toString(),3);
480 JPanel velocitypanel = new JPanel();
481 velocitypanel.add(new Label("Velocity: "));
482 velocitypanel.add(velocity);
484 length = new JTextField(new Integer(note.getDuration()).toString(),5);
485 JPanel lengthpanel = new JPanel();
486 lengthpanel.add(new Label("Length: "));
487 lengthpanel.add(length);
489 Object[] array = {"Set the note properties",
494 final String btnString1 = "Apply changes";
495 final String btnString2 = "Cancel";
496 Object[] options = {btnString1, btnString2};
498 optionPane = new JOptionPane(array,
499 JOptionPane.QUESTION_MESSAGE,
500 JOptionPane.YES_NO_OPTION,
504 setContentPane(optionPane);
505 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
507 ActionListener intValidator = new ActionListener() {
508 public void actionPerformed(ActionEvent e) {
509 if (e.getSource() instanceof JTextField){
510 JTextField s = (JTextField)e.getSource();
511 int num = Integer.parseInt(s.getText());
514 else if (num > 127 && s != length)
516 s.setText(new Integer(num).toString());
520 pitch.addActionListener(intValidator);
521 velocity.addActionListener(intValidator);
522 length.addActionListener(intValidator);
524 optionPane.addPropertyChangeListener(new PropertyChangeListener() {
525 public void propertyChange(PropertyChangeEvent e) {
526 String prop = e.getPropertyName();
529 && (e.getSource() == optionPane)
530 && (prop.equals(JOptionPane.VALUE_PROPERTY) ||
531 prop.equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
532 Object value = optionPane.getValue();
534 if (value == JOptionPane.UNINITIALIZED_VALUE) {
539 // Reset the JOptionPane's value.
540 // If you don't do this, then if the user
541 // presses the same button next time, no
542 // property change event will be fired.
544 JOptionPane.UNINITIALIZED_VALUE);
546 if (value.equals(btnString1)) {
547 note.setPitch(Integer.parseInt(pitch.getText()));
548 note.setVelocity(Integer.parseInt(velocity.getText()));
549 note.setDuration(Integer.parseInt(length.getText()));
550 Moosique.setEdited();
552 } else { // user closed dialog or clicked cancel