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, labelG, labelH;
17 private JTextField textFieldA, textFieldB, textFieldC, textFieldD, textFieldE, textFieldF,
18 textFieldG, textFieldH, textFieldI, textFieldJ, textFieldK;
19 private JComboBox trackListA, trackListB;
20 private JButton okButton, cancelButton;
21 public static final int ADD_TRACK = 1,
34 * Constructor of the dialogs.
36 public MooDialog(int type) {
37 super(Moosique.getGUI(), false);
39 Container pane = getContentPane();
42 Track[] tracks = Moosique.getSequence().getTracks();
45 case ADD_TRACK: makeAddDialog(pane, tracks); break;
46 case DELETE_TRACK: makeDelDialog(pane, tracks); break;
47 case COPY_TRACK: makeCopyDialog(pane, tracks); break;
48 case MOVE_TRACK: makeMoveDialog(pane, tracks); break;
49 case SET_POSITION: makeSetPositionDialog(pane); break;
50 case MANUAL: makeTextDialog(pane, "Manual.txt"); break;
51 case INSERT_MEASURE: makeInsertMeasureDialog(pane); break;
52 case DELETE_MEASURE: makeDeleteMeasureDialog(pane); break;
53 case SET_TEMPO: makeSetTempoDialog(pane); break;
54 case PREFERENCES: makePrefsDialog(pane); break;
55 case TRANSPOSE: makeTransposeDialog(pane, tracks); break;
60 * Builds the add track popupdialog.
61 * @param pane The container to put the dialog in.
62 * @param tracks A array containing miditracks.
64 private void makeAddDialog(Container pane, Track[] tracks) {
66 setTitle("Add track");
67 labelA = new JLabel("Name of track", JLabel.CENTER);
69 textFieldA = new JTextField();
71 labelB = new JLabel("Add after", JLabel.CENTER);
73 trackListA = new JComboBox();
74 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
76 cancelButton = new JButton("Cancel");
77 pane.add(cancelButton);
78 okButton = new JButton("OK");
81 labelA.setBounds(50, 10, 100, 20);
82 textFieldA.setBounds(40, 35, 120, 20);
83 labelB.setBounds(50, 70, 100, 20);
84 trackListA.setBounds(40, 95, 120, 20);
85 cancelButton.setBounds(10, 150, 80, 30);
86 okButton.setBounds(120, 150, 60, 30);
91 setLocationRelativeTo(Moosique.getGUI());
96 * Builds the delete track popupdialog.
97 * @param pane The container to put the dialog in.
98 * @param tracks A array containing miditracks.
100 private void makeDelDialog(Container pane, Track[] tracks) {
102 setTitle("Delete track");
103 labelB = new JLabel("Delete track", JLabel.CENTER);
105 trackListA = new JComboBox();
106 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
107 pane.add(trackListA);
108 cancelButton = new JButton("Cancel");
109 pane.add(cancelButton);
110 okButton = new JButton("OK");
113 labelB.setBounds(50, 10, 100, 20);
114 trackListA.setBounds(40, 35, 120, 20);
115 cancelButton.setBounds(10, 90, 80, 30);
116 okButton.setBounds(120, 90, 60, 30);
121 setLocationRelativeTo(Moosique.getGUI());
126 * Builds the copy track popupdialog.
127 * @param pane The container to put the dialog in.
128 * @param tracks A array containing miditracks.
130 private void makeCopyDialog(Container pane, Track[] tracks) {
132 setTitle("Copy Track");
133 labelA = new JLabel("Track to copy", JLabel.CENTER);
135 trackListA = new JComboBox();
136 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
137 pane.add(trackListA);
138 labelB = new JLabel("Insert after", JLabel.CENTER);
140 trackListB = new JComboBox();
141 for (int i = 1; i <= tracks.length; i++) trackListB.addItem("Track " + i);
142 pane.add(trackListB);
143 cancelButton = new JButton("Cancel");
144 pane.add(cancelButton);
145 okButton = new JButton("OK");
148 labelA.setBounds(50, 10, 100, 20);
149 trackListA.setBounds(40, 35, 120, 20);
150 labelB.setBounds(50, 70, 100, 20);
151 trackListB.setBounds(40, 95, 120, 20);
152 cancelButton.setBounds(10, 150, 80, 30);
153 okButton.setBounds(120, 150, 60, 30);
158 setLocationRelativeTo(Moosique.getGUI());
163 * Builds the move track popupdialog
164 * @param pane The container to put the dialog in.
165 * @param tracks A array containing miditracks.
167 private void makeMoveDialog(Container pane, Track[] tracks) {
169 setTitle("Move track");
170 labelA = new JLabel("Track to move", JLabel.CENTER);
172 trackListA = new JComboBox();
173 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
174 pane.add(trackListA);
175 labelB = new JLabel("Insert after", JLabel.CENTER);
177 trackListB = new JComboBox();
178 for (int i = 1; i <= tracks.length; i++) trackListB.addItem("Track " + i);
179 pane.add(trackListB);
180 cancelButton = new JButton("Cancel");
181 pane.add(cancelButton);
182 okButton = new JButton("OK");
185 labelA.setBounds(40, 10, 120, 20);
186 trackListA.setBounds(40, 35, 120, 20);
187 labelB.setBounds(50, 70, 100, 20);
188 trackListB.setBounds(40, 95, 120, 20);
189 cancelButton.setBounds(10, 150, 80, 30);
190 okButton.setBounds(120, 150, 60, 30);
195 setLocationRelativeTo(Moosique.getGUI());
200 * Builds the set position dialog.
201 * @param pane The container to put the dialog in.
202 * @param tracks A array containing miditracks.
204 private void makeSetPositionDialog(Container pane) {
206 setTitle("Set edit position");
207 labelA = new JLabel("Measure", JLabel.CENTER);
209 labelB = new JLabel("Beat", JLabel.CENTER);
211 labelC = new JLabel("Tick", JLabel.CENTER);
213 textFieldA = new JTextField();
214 pane.add(textFieldA);
215 textFieldB = new JTextField();
216 pane.add(textFieldB);
217 textFieldC = new JTextField();
218 pane.add(textFieldC);
219 cancelButton = new JButton("Cancel");
220 pane.add(cancelButton);
221 okButton = new JButton("OK");
224 labelA.setBounds(40, 25, 50, 20);
225 labelB.setBounds(105, 25, 50, 20);
226 labelC.setBounds(170, 25, 50, 20);
227 textFieldA.setBounds(40, 45, 50, 20);
228 textFieldB.setBounds(105, 45, 50, 20);
229 textFieldC.setBounds(170, 45, 50, 20);
230 cancelButton.setBounds(35, 90, 80, 30);
231 okButton.setBounds(155, 90, 60, 30);
236 setLocationRelativeTo(Moosique.getGUI());
241 * Builds the insert measure popupdialog.
242 * @param pane The container to put the dialog in.
244 private void makeInsertMeasureDialog(Container pane){
246 setTitle("Insert Measure");
247 labelA = new JLabel("Insert at:", JLabel.RIGHT);
249 labelB = new JLabel("Measure count:", JLabel.RIGHT);
251 textFieldA = new JTextField();
252 pane.add(textFieldA);
253 textFieldB = new JTextField();
254 pane.add(textFieldB);
255 cancelButton = new JButton("Cancel");
256 pane.add(cancelButton);
257 okButton = new JButton("OK");
260 labelA.setBounds(20, 20, 110 ,20);
261 labelB.setBounds(20, 50, 110, 20);
262 textFieldA.setBounds(140 ,20 , 40, 20);
263 textFieldB.setBounds(140,50, 40, 20);
264 cancelButton.setBounds(20 ,95 , 80, 30);
265 okButton.setBounds(120, 95, 60, 30);
270 setLocationRelativeTo(Moosique.getGUI());
275 * Builds the delete measure popupdialog.
276 * @param pane The container to put the dialog in.
278 private void makeDeleteMeasureDialog(Container pane) {
280 setTitle("Delete Measure");
281 labelA = new JLabel("Delete at:", JLabel.RIGHT);
283 labelB = new JLabel("Measure count:", JLabel.RIGHT);
285 textFieldA = new JTextField();
286 pane.add(textFieldA);
287 textFieldB = new JTextField();
288 pane.add(textFieldB);
289 cancelButton = new JButton("Cancel");
290 pane.add(cancelButton);
291 okButton = new JButton("OK");
294 labelA.setBounds(20, 20, 110 ,20);
295 labelB.setBounds(20, 50, 110, 20);
296 textFieldA.setBounds(140 ,20 , 40, 20);
297 textFieldB.setBounds(140,50, 40, 20);
298 cancelButton.setBounds(20 ,95 , 80, 30);
299 okButton.setBounds(120, 95, 60, 30);
304 setLocationRelativeTo(Moosique.getGUI());
309 * Builds the set tempo dialog.
310 * @param pane The container to put the dialog in.
312 private void makeSetTempoDialog(Container pane) {
314 setTitle("Set tempo");
316 // create contents of dialog and add to container
317 // track edit-intervall labels
318 labelA = new JLabel("Measure", JLabel.CENTER);
320 labelB = new JLabel("Beat", JLabel.CENTER);
322 labelC = new JLabel("Tick", JLabel.CENTER);
324 // start and end labels
325 labelD = new JLabel("Start at:", JLabel.RIGHT);
327 labelE = new JLabel("End at:", JLabel.RIGHT);
330 labelF = new JLabel("to", JLabel.CENTER);
332 // start inputvaluefields
333 textFieldA = new JTextField();
334 pane.add(textFieldA);
335 textFieldB = new JTextField();
336 pane.add(textFieldB);
337 textFieldC = new JTextField();
338 pane.add(textFieldC);
339 // end inputvaluefield
340 textFieldD = new JTextField();
341 pane.add(textFieldD);
342 textFieldE = new JTextField();
343 pane.add(textFieldE);
344 textFieldF = new JTextField();
345 pane.add(textFieldF);
346 // the radiobuttonlists inputvaluefields
347 textFieldG = new JTextField();
348 pane.add(textFieldG);
349 textFieldH = new JTextField();
350 pane.add(textFieldH);
351 textFieldI = new JTextField();
352 pane.add(textFieldI);
353 textFieldJ = new JTextField();
354 pane.add(textFieldJ);
355 textFieldK = new JTextField();
356 pane.add(textFieldK);
357 // the radiobuttonlist with associating titles
358 JRadioButton constant = new JRadioButton("Set constant tempo of:");
359 constant.setSelected(true);
361 JRadioButton change = new JRadioButton("Gradually change tempo:");
363 JRadioButton scale = new JRadioButton("Scale tempo in %:");
365 JRadioButton add = new JRadioButton("Add to current tempo:");
367 // a buttongroup for the radiobuttons
368 ButtonGroup group = new ButtonGroup();
373 // ok and cancelbutton
374 cancelButton = new JButton("Cancel");
375 pane.add(cancelButton);
376 okButton = new JButton("OK");
379 // set bounds of track edit-intervall labels
380 labelA.setBounds(80, 25, 50, 20);
381 labelB.setBounds(145, 25, 50, 20);
382 labelC.setBounds(210, 25, 50, 20);
383 // set bounds of start and end labels
384 labelD.setBounds(20, 45, 60, 20);
385 labelE.setBounds(20, 65, 60, 20);
386 // set bounds of from-to label
387 labelF.setBounds(255, 125, 20 ,20);
388 // set bounds of start inputvaluefields
389 textFieldA.setBounds(80, 45, 50, 20);
390 textFieldB.setBounds(145, 45, 50, 20);
391 textFieldC.setBounds(210, 45, 50, 20);
392 // set bounds of end inputvaluefield
393 textFieldD.setBounds(80, 65, 50, 20);
394 textFieldE.setBounds(145, 65, 50, 20);
395 textFieldF.setBounds(210, 65, 50, 20);
396 // set bounds of radiobuttonlists inputvaluefields
397 textFieldG.setBounds(220, 100, 35, 20);
398 textFieldH.setBounds(220, 125, 35, 20);
399 textFieldI.setBounds(280, 125, 35, 20);
400 textFieldJ.setBounds(220, 150, 35, 20);
401 textFieldK.setBounds(220, 175, 35, 20);
402 // set bounds of radiobuttonlist items
403 constant.setBounds(20, 100, 180, 20);
404 change.setBounds(20, 125, 200, 20);
405 scale.setBounds(20, 150, 150, 20);
406 add.setBounds(20, 175, 175, 20);
407 // set bounds of ok and cancelbutton
408 cancelButton.setBounds(75, 215, 80, 30);
409 okButton.setBounds(195, 215, 60, 30);
414 setLocationRelativeTo(Moosique.getGUI());
419 * Builds the transpose dialog.
420 * @param pane The container to put the dialog in.
421 * @param tracks A array containing miditracks.
423 private void makeTransposeDialog(Container pane, Track[] tracks) {
425 setTitle("Transpose");
426 // create contents of dialog and add to container
427 // track edit-intervall labels
428 labelA = new JLabel("Measure", JLabel.CENTER);
430 labelB = new JLabel("Beat", JLabel.CENTER);
432 labelC = new JLabel("Tick", JLabel.CENTER);
434 // start and end labels
435 labelD = new JLabel("Start at:", JLabel.RIGHT);
437 labelE = new JLabel("End at:", JLabel.RIGHT);
439 // oktave inputvalue labels
440 labelF = new JLabel("Octaves", JLabel.LEFT);
442 labelG = new JLabel("1/2 octaves", JLabel.LEFT);
444 // what track to edig label
445 labelH = new JLabel("Track to edit:", JLabel.CENTER);
447 // combobox representing the tracks
448 trackListA = new JComboBox();
449 for (int i = 1; i <= tracks.length; i++) trackListA.addItem("Track " + i);
450 pane.add(trackListA);
451 // start inputvaluefields
452 textFieldA = new JTextField();
453 pane.add(textFieldA);
454 textFieldB = new JTextField();
455 pane.add(textFieldB);
456 textFieldC = new JTextField();
457 pane.add(textFieldC);
458 // end inputvaluefield
459 textFieldD = new JTextField();
460 pane.add(textFieldD);
461 textFieldE = new JTextField();
462 pane.add(textFieldE);
463 textFieldF = new JTextField();
464 pane.add(textFieldF);
465 // the radiobuttonlists inputvaluefields
466 textFieldG = new JTextField();
467 pane.add(textFieldG);
468 textFieldH = new JTextField();
469 pane.add(textFieldH);
470 // the radiobuttonlist with associating titles
471 JRadioButton up = new JRadioButton("Change up");
472 up.setSelected(true);
474 JRadioButton down = new JRadioButton("Change down");
476 // a buttongroup for the radiobuttons
477 ButtonGroup group = new ButtonGroup();
480 // ok and cancelbutton
481 cancelButton = new JButton("Cancel");
482 pane.add(cancelButton);
483 okButton = new JButton("OK");
486 // set bounds of track edit-intervall labels
487 labelA.setBounds(90, 70, 50, 20);
488 labelB.setBounds(155, 70, 50, 20);
489 labelC.setBounds(220, 70, 50, 20);
490 // set bounds of start and end labels
491 labelD.setBounds(30, 90, 60, 20);
492 labelE.setBounds(30, 110, 60, 20);
493 // set bounds of octave inputvaluefields
494 labelF.setBounds(210, 150, 80, 20);
495 labelG.setBounds(210, 175, 100, 20);
496 // set bounds of trackslist label
497 labelH.setBounds(30, 30, 100, 20);
498 // set bounds of start inputvaluefields
499 textFieldA.setBounds(90, 90, 50, 20);
500 textFieldB.setBounds(155, 90, 50, 20);
501 textFieldC.setBounds(220, 90, 50, 20);
502 // set bounds of end inputvaluefield
503 textFieldD.setBounds(90, 110, 50, 20);
504 textFieldE.setBounds(155, 110, 50, 20);
505 textFieldF.setBounds(220, 110, 50, 20);
506 // set bounds of octave inputvaluefields
507 textFieldG.setBounds(170, 150, 35, 20);
508 textFieldH.setBounds(170, 175, 35, 20);
509 // set bounds of radiobuttonlist items
510 up.setBounds(30, 150, 100, 20);
511 down.setBounds(30, 175, 120, 20);
512 // set bounds of tracklist
513 trackListA.setBounds(145, 30, 120, 20);
514 // set bounds of ok and cancelbutton
515 cancelButton.setBounds(75, 215, 80, 30);
516 okButton.setBounds(195, 215, 60, 30);
521 setLocationRelativeTo(Moosique.getGUI());
525 private void makeTextDialog(Container pane, String filename) {
526 setTitle("User Manual");
527 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
528 File manual = new File(filename);
531 BufferedReader br = new BufferedReader(new FileReader(manual));
532 char[] chars = new char[(int)manual.length()];
533 br.read(chars, 0, (int)manual.length());
534 s = new String(chars);
535 } catch (Exception ex) {
536 s = "Manual not found";
538 pane.add(new JScrollPane(new JTextArea(s, 30, 95)));
539 Action close = new AbstractAction("Close") {
540 public void actionPerformed(ActionEvent ae) {
543 JButton closeButton = new JButton(close);
544 closeButton.setAlignmentX(Component.CENTER_ALIGNMENT);
545 pane.add(closeButton);
548 setLocationRelativeTo(Moosique.getGUI());
552 private void makePrefsDialog(Container pane) {
554 MidiDevice.Info[] devInfo = MidiSystem.getMidiDeviceInfo();
555 for (int i = 0; i < devInfo.length; i++) {
556 if (MidiSystem.getMidiDevice(devInfo[i]) instanceof Sequencer) {
558 } else if (MidiSystem.getMidiDevice(devInfo[i]) instanceof Synthesizer) {
562 String[] seqNames, synthNames;
563 JPanel pane = (JPanel) this.getContentPane();
564 pane.add(new JLabel("Sequencer"));
565 JComboBox seqBox = new JComboBox(seqNames);
566 pane.add(new JLabel("Synthesizer"));
567 JComboBox synthBox = new JComboBox(synthNames);
571 private MooNote note;
572 private JOptionPane optionPane;
573 private JTextField pitch;
574 private JTextField velocity;
575 private JTextField length;
578 * Creates a new note preference dialog.
579 * @param mn the note that will be graphically represented
581 public MooDialog(MooNote mn) {
582 super(Moosique.getGUI(), "Note properties", true);
583 JPanel panel = new JPanel();
584 panel.setLayout(new GridLayout(3,2));
586 pitch = new JTextField(new Integer(note.getPitch()).toString(),3);
587 panel.add(new Label("Pitch: "));
590 velocity = new JTextField(new Integer(note.getVelocity()).toString(),3);
591 panel.add(new Label("Velocity: "));
594 length = new JTextField(new Integer(note.getDuration()).toString(),5);
595 panel.add(new Label("Length: "));
598 Object[] array = {"Set the note properties",
601 final String btnString1 = "Apply changes";
602 final String btnString2 = "Cancel";
603 Object[] options = {btnString1, btnString2};
605 optionPane = new JOptionPane(array,
606 JOptionPane.QUESTION_MESSAGE,
607 JOptionPane.YES_NO_OPTION,
611 setContentPane(optionPane);
612 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
614 ActionListener intValidator = new ActionListener() {
615 public void actionPerformed(ActionEvent e) {
616 if (e.getSource() instanceof JTextField){
617 JTextField s = (JTextField)e.getSource();
618 int num = Integer.parseInt(s.getText());
621 else if (num > 127 && s != length)
623 s.setText(new Integer(num).toString());
627 pitch.addActionListener(intValidator);
628 velocity.addActionListener(intValidator);
629 length.addActionListener(intValidator);
631 optionPane.addPropertyChangeListener(new PropertyChangeListener() {
632 public void propertyChange(PropertyChangeEvent e) {
633 String prop = e.getPropertyName();
636 && (e.getSource() == optionPane)
637 && (prop.equals(JOptionPane.VALUE_PROPERTY) ||
638 prop.equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
639 Object value = optionPane.getValue();
641 if (value == JOptionPane.UNINITIALIZED_VALUE) {
646 // Reset the JOptionPane's value.
647 // If you don't do this, then if the user
648 // presses the same button next time, no
649 // property change event will be fired.
651 JOptionPane.UNINITIALIZED_VALUE);
653 if (value.equals(btnString1)) {
654 note.setPitch(Integer.parseInt(pitch.getText()));
655 note.setVelocity(Integer.parseInt(velocity.getText()));
656 note.setDuration(Integer.parseInt(length.getText()));
657 Moosique.setEdited();
659 } else { // user closed dialog or clicked cancel