001package net.kreatious.pianoleopard;
002
003import java.awt.FlowLayout;
004import java.awt.Toolkit;
005import java.awt.event.WindowAdapter;
006import java.awt.event.WindowEvent;
007import java.io.File;
008import java.io.IOException;
009import java.util.prefs.Preferences;
010
011import javax.swing.JFrame;
012import javax.swing.JOptionPane;
013import javax.swing.JPanel;
014import javax.swing.UIManager;
015import javax.swing.plaf.nimbus.NimbusLookAndFeel;
016
017import net.kreatious.pianoleopard.history.History;
018import net.kreatious.pianoleopard.keyboardselect.SelectKeyboardDialog;
019import net.kreatious.pianoleopard.midi.InputModel;
020import net.kreatious.pianoleopard.midi.OutputModel;
021import net.kreatious.pianoleopard.midi.SystemSequencerFactory;
022import net.kreatious.pianoleopard.painter.PainterPanel;
023
024import com.jgoodies.forms.factories.FormFactory;
025import com.jgoodies.forms.layout.ColumnSpec;
026import com.jgoodies.forms.layout.FormLayout;
027import com.jgoodies.forms.layout.RowSpec;
028
029/**
030 * Provides the main application interface for learning how to play the piano.
031 *
032 * @author Jay-R Studer
033 */
034public class Main {
035    /**
036     * Application main entry point
037     *
038     * @param args
039     *            unused
040     */
041    public static void main(String[] args) {
042        try {
043            UIManager.setLookAndFeel(new NimbusLookAndFeel());
044
045            final OutputModel outputModel = new OutputModel(new SystemSequencerFactory());
046            final InputModel inputModel = InputModel.create(outputModel);
047            final JFrame applet = create(outputModel, inputModel);
048            applet.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
049            applet.setIconImage(Toolkit.getDefaultToolkit().getImage(
050                    SelectKeyboardDialog.class.getResource("/application_lightning.png")));
051            applet.setTitle("Piano Leopard");
052            applet.setVisible(true);
053        } catch (final Exception e) {
054            e.printStackTrace();
055            JOptionPane.showMessageDialog(null, "Unable to continue: " + e.getMessage(), "Error",
056                    JOptionPane.ERROR_MESSAGE);
057        }
058    }
059
060    private static JFrame create(OutputModel outputModel, InputModel inputModel) {
061        AntiIdle.create(inputModel);
062
063        final Preferences preferences = Preferences.userNodeForPackage(Main.class);
064        LightedKeyboardController.create(preferences, outputModel, inputModel);
065        final JFrame frame = new JFrame();
066        frame.setLayout(new FormLayout(new ColumnSpec[] { FormFactory.RELATED_GAP_COLSPEC, FormFactory.DEFAULT_COLSPEC,
067                FormFactory.RELATED_GAP_COLSPEC, FormFactory.BUTTON_COLSPEC, FormFactory.RELATED_GAP_COLSPEC,
068                FormFactory.BUTTON_COLSPEC, ColumnSpec.decode("default:grow"), FormFactory.DEFAULT_COLSPEC,
069                FormFactory.DEFAULT_COLSPEC }, new RowSpec[] { FormFactory.RELATED_GAP_ROWSPEC,
070                FormFactory.DEFAULT_ROWSPEC, FormFactory.MIN_ROWSPEC, RowSpec.decode("fill:default:grow") }));
071        frame.add(TempoController.create(outputModel), "8, 2, 2, 2, right, top");
072        frame.add(PracticeController.create(outputModel), "6, 2");
073        frame.add(OpenController.create(frame, preferences, outputModel), "4, 2");
074        frame.add(KeyboardController.create(frame, preferences, outputModel, inputModel), "2, 2");
075        frame.add(PainterPanel.create(outputModel, inputModel), "1, 4, 7, 1, fill, fill");
076        frame.add(CurrentPositionController.create(outputModel), "8, 4");
077
078        final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
079        panel.add(PracticeTrackController.create(outputModel));
080        panel.add(PlayAlongController.create(outputModel));
081        panel.add(PracticeTimeController.create(History.create(new File("log.dat"), outputModel, inputModel),
082                outputModel));
083        frame.add(panel, "2, 3, 6, 1");
084
085        frame.pack();
086        frame.addWindowListener(new WindowAdapter() {
087            @Override
088            public void windowClosing(WindowEvent e) {
089                try {
090                    outputModel.close();
091                    inputModel.close();
092                } catch (final InterruptedException ex) {
093                    Thread.currentThread().interrupt();
094                } catch (final IOException ex) {
095                    ex.printStackTrace();
096                }
097            }
098        });
099        return frame;
100    }
101}