Main.java

/**
* Copyright (c) 2012-2013 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
* Oracle and Java are trademarks or registered trademarks of Oracle and/or its
* affiliates. Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners. 
* See LICENSE.TXT for license information.
*/
package com.nokia.example.racer;

import com.nokia.example.racer.gestures.GestureProvider;
import com.nokia.example.racer.views.GameView;
import com.nokia.example.racer.views.MenuView;
import com.nokia.example.racer.views.SettingsView;
import com.nokia.example.racer.views.SplashView;
import com.nokia.example.racer.views.components.Track;
import com.nokia.example.racer.views.tracks.EightLoop;
import com.nokia.example.racer.views.tracks.Monza;
import com.nokia.example.racer.views.tracks.Oval;
import com.nokia.mid.ui.DeviceControl;
import com.nokia.mid.ui.VirtualKeyboard;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.MIDlet;

/**
 * Main class to handle starting, pausing and exiting the application.
 */
public class Main
    extends MIDlet
    implements ExitListener, CommandListener {

    public static boolean sensorsSupported;  // indicates if the device supports acceleration sensors
    public static boolean gesturesSupported;  // indicates if the device supports gestures
    public static boolean landscape;  // indicates if the device supports landscape mode
    private static Main self;
    private Display display;
    /*
     * views for the actual racing, menu, and settings
     */
    private GameView gameView;
    private MenuView menuView;
    private SettingsView settingsView;

    public static Command backCommand;
    private Command cancelCommand;
    private Command okCommand;
    private Track track;

    public static Main getInstance() {
        return self;
    }

    /**
     * Starts the app by showing splash screen and initializes views
     * @see javax.microedition.midlet.MIDlet#startApp()
     */
    public void startApp() {
        if (display == null) {
            display = Display.getDisplay(this);
            self = this;

            DeviceControl.setLights(0, 100);  // prevent screen saving

            /*
             * first show a splash screen
             */
            SplashView splashView = new SplashView();
            display.setCurrent(splashView);

            // Hide open virtual keypad -command as it is not needed here.
            if (hasOnekeyBack()) {
                VirtualKeyboard.hideOpenKeypadCommand(true);
                VirtualKeyboard.suppressSizeChanged(true);
            }
            backCommand = new Command("Back", Command.BACK, 1);
            okCommand = new Command("Ok", Command.OK, 1);
            cancelCommand = new Command("Cancel", Command.BACK, 1);

            /*
             * load other views in the background
             */
            new Thread() {

                public void run() {
                    gameView = new GameView();
                    // enable gestures needed in GameView
                    gesturesSupported = GestureProvider.enableGestures();

                    menuView = new MenuView();
                    settingsView = new SettingsView();

                    try {
                        sleep(1000);
                    }
                    catch (InterruptedException e) {
                    }

                    addCommands();
                    showMenu();  // when ready, show menu

                    try {
                        join();
                    }
                    catch (InterruptedException e) {
                    }
                }
            }.start();
            splashView = null;
        }
    }

    /**
     * A method that must be implemented by CommandListener.
     * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
     * 
     * @param c the type of command
     * @param d displayable the command originated from
     */
    public void commandAction(Command c, Displayable d) {
        if (c == List.SELECT_COMMAND) {
            int selected = settingsView.getSelectedIndex();
            String trackName = "";

            if (selected == 0) {
                trackName = "EightLoop";
            }
            else if (selected == 1) {
                trackName = "Monza";
            }
            else if (selected == 2) {
                trackName = "Oval";
            }
            // Inform user of the selected track.
            Alert selectedAlert = new Alert("Select", "Select " + trackName + " track?", null, AlertType.INFO);
            selectedAlert.addCommand(okCommand);
            selectedAlert.addCommand(cancelCommand);
            selectedAlert.setCommandListener(this);
            selectedAlert.setTimeout(Alert.FOREVER);
            display.setCurrent(selectedAlert);
        }
        else if (c == backCommand || c == cancelCommand) {
            if (c == cancelCommand) {
                // Only alert in the application for settings view takes back there.
                showSettings();
            }
            else if (!(d instanceof MenuView)) {
                showMenu();
            } 
            else {
                exit();
            }
        }
        else if (c == okCommand) {
            int selected = settingsView.getSelectedIndex();
            gameView.cleanTrackResources();
            // Set track based on selected list index.
            if (selected == 0) {
                track = new EightLoop(gameView);
            }
            else if (selected == 1) {
                track = new Monza(gameView);
            }
            else if (selected == 2) {
                track = new Oval(gameView);
            }
            gameView.setTrack(track);
            showMenu();
        }
    }

    public void showGameView() {
        if (track != null) {
            gameView.setTrack(track);
        }
        display.setCurrent(gameView);
    }

    public void showMenu() {
        display.setCurrent(menuView);
    }

    public void showSettings() {
        display.setCurrent(settingsView);
    }

    /**
     * Pauses the app.
     * @see javax.microedition.midlet.MIDlet#pauseApp()
     */
    public void pauseApp() {
    }

    /**
     * Exits the app.
     * @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
     * @param unconditional should the midlet clean up and release all resources
     */
    public void destroyApp(boolean unconditional) {
    }

    public void exit() {
        destroyApp(false);
        notifyDestroyed();
    }

    public Display getDisplay() {
        return display;
    }

    public GameView getGameView() {
        return gameView;
    }

    private void addCommands() {
        gameView.addCommand(backCommand);
        gameView.setCommandListener(this);
        if(System.getProperty("com.nokia.keyboard.type").equals("OnekeyBack")) {
            menuView.addCommand(backCommand);
            menuView.setCommandListener(this);
        }
        settingsView.addCommand(backCommand);
        settingsView.setCommandListener(this);
    }

    /**
     * If the device has a hardware back key, hide virtual keyboard.
     * This check is needed for backward compatibility with older 
     * devices without virtual keyboard.
     * @return true or false
     */
    private boolean hasOnekeyBack() {
        String keyboard = System.getProperty("com.nokia.keyboard.type");
        if (keyboard != null) {
            return (keyboard.equalsIgnoreCase("OnekeyBack"));
        } else {
            return false;
        }
    }
}