MainView.java

/**
 * Copyright (c) 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.fileselectexample;

import com.nokia.mid.ui.FileSelect;
import com.nokia.mid.ui.FileSelectDetail;

import javax.microedition.io.ConnectionNotFoundException;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;

/**
 * The main view of the application. Contains the ChoiceGroups for selecting
 * the details for the file selector. This Form also handles all the Commands
 * in the application.
 */
public class MainView
       extends Form
       implements CommandListener, 
                  ItemStateListener,
                  FileView.Listener
{
    // Constants

    // FileSelect API has file system root locations predefined (e.g.
    // FileSelect.FILE_SYSTEM_EXTERNAL meaning the memory card). The API also
    // allows defining the initial location for the selector as an URL. The
    // following constants define which one of the above approaches to use.
    private static final int MODE_API_DEFINED = 0;
    private static final int MODE_BASED_ON_URL = 1;
    private static final String[] MODE_CHOICES =
        { "API defined", "System property URLs" };
    private static final String[] FILE_SYSTEMS =
        { FileSelect.FILE_SYSTEM_ALL,
          FileSelect.FILE_SYSTEM_INTERNAL,
          FileSelect.FILE_SYSTEM_EXTERNAL };

    // Enumeration for different file types
    private static final int API_FILE_TYPE_ALL = 0;
    private static final int API_FILE_TYPE_PICTURE = 1;
    private static final int API_FILE_TYPE_AUDIO = 2;
    private static final int API_FILE_TYPE_VIDEO = 3;
    private static final int API_FILE_TYPE_APPLICATION = 4;
    private static final String[] API_FILE_TYPES =
        { "All", "Pictures", "Audio", "Videos", "Applications" };

    private static final int URL_FILE_TYPE_MUSIC = 0;
    private static final int URL_FILE_TYPE_PHOTOS = 1;
    private static final int URL_FILE_TYPE_VIDEO = 2;
    private static final String[] URL_FILE_TYPES =
        { "Music", "Photos", "Videos" };

    // Members
    private Main midlet;
    private FileView fileView;
    private ChoiceGroup modeChoiceGroup;
    private ChoiceGroup fileSystemChoiceGroup;
    private ChoiceGroup fileTypeChoiceGroup;

    private final Command selectMultipleFilesCommand = new Command("Select multiple files", Command.SCREEN, 1);
    private final Command selectSingleFileCommand = new Command("Select single file", Command.SCREEN, 2);
    private final Command exitCommand = new Command("Exit", Command.EXIT, 1);
    private final Command backCommand = new Command("Back", Command.BACK, 1);
    private final Command openFileCommand = new Command("Open File", Command.SCREEN, 1);

    private int currentMode = -1; // Contains the selected mode (API defined/URL based)

    /**
     * Constructor.
     */
    public MainView(String title, Main midlet) {
        super(title);
        this.midlet = midlet;
        
        modeChoiceGroup =
            new ChoiceGroup("Tap to select the mode", Choice.POPUP, MODE_CHOICES, null);
        fileSystemChoiceGroup =
            new ChoiceGroup("Tap to select the file system", Choice.POPUP, FILE_SYSTEMS, null);
        
        setMode(MODE_API_DEFINED);
        
        addCommand(selectMultipleFilesCommand);
        addCommand(selectSingleFileCommand);
        addCommand(exitCommand);
        
        setCommandListener(this);
        setItemStateListener(this);
        
        fileView = new FileView(this);
        fileView.addCommand(backCommand);
        fileView.addCommand(openFileCommand);
        fileView.setCommandListener(this);
    }

    /**
     * @see javax.microedition.lcdui.CommandListener#commandAction(Command, Displayable)
     */
    public void commandAction(Command command, Displayable displayable) {
        if (command == selectMultipleFilesCommand
            || command == selectSingleFileCommand)
        {
            boolean multipleSelection = (command == selectMultipleFilesCommand);
            
            if (currentMode == MODE_API_DEFINED) {
                fileView.getSelectedFiles(getStartUrl(),
                                          getMediaType(),
                                          multipleSelection);
            }
            else {
                // MODE_BASED_ON_URL
                fileView.getSelectedFiles(getStartUrl(),
                                          FileSelect.MEDIA_TYPE_ALL,
                                          multipleSelection);
            }
        }
        else if (command == exitCommand) {
            midlet.quit();
        }
        else if (command == backCommand) {
            Display.getDisplay(midlet).setCurrent(this);
        }
        else if (command == openFileCommand) {
            // Open the selected file
            onFileSelected(fileView.getSelectedFileDetails());
        }
    }

    /**
     * @see javax.microedition.lcdui.ItemStateListener#itemStateChanged(Item)
     */
    public void itemStateChanged(Item item) {
        if (item == modeChoiceGroup) {
            setMode(modeChoiceGroup.getSelectedIndex());
        }
    }

    /**
     * @see FileView.Listener#onMultipleFilesSelected(int)
     */
    public void onMultipleFilesSelected(int count) {
        // Show the selected files in the file view form.
        Display.getDisplay(midlet).setCurrent(fileView);
    }

    /**
     * @see FileView.Listener#onFileSelected(FileSelectDetail)
     */
    public void onFileSelected(FileSelectDetail fileDetails) {
        System.out.println("MainView::onFileSelected(): " + fileDetails.url);
        
        if (fileDetails != null) {
            // Open the selected file
            try {
                midlet.platformRequest(fileDetails.url);
            }
            catch (ConnectionNotFoundException e) {
                System.out.println(e.toString());
                e.printStackTrace();
            }
        }
    }

    /**
     * @see FileView.Listener#onError()
     */
    public void onError(String errorMessage) {
        Alert errorAlert = new Alert("Error", errorMessage, null, AlertType.ERROR);
        Display.getDisplay(midlet).setCurrent(errorAlert);
    }

    /**
     * Sets the mode to either API defined locations or URL defined locations.
     * @param mode The mode to set (MODE_API_DEFINED or MODE_BASED_ON_URL).
     */
    private void setMode(final int mode) {
        if (currentMode == mode) {
            return;
        }
        
        currentMode = mode;
        
        switch (currentMode) {
            case MODE_API_DEFINED:
                deleteAll();
                append(modeChoiceGroup);
                append(fileSystemChoiceGroup);
                fileTypeChoiceGroup =
                    new ChoiceGroup("Tap to select file type", Choice.POPUP,
                       API_FILE_TYPES, null);
                append(fileTypeChoiceGroup);
                break;
            case MODE_BASED_ON_URL:
                deleteAll();
                append(modeChoiceGroup);
                fileTypeChoiceGroup =
                    new ChoiceGroup("Tap to select file type", Choice.POPUP,
                        URL_FILE_TYPES, null);
                append(fileTypeChoiceGroup);
                break;
            default:
                System.out.println("MainView::setMode(): Invalid mode!");
                break;
        }
    }

    /**
     * Resolves the initial URL for the file selector based on the current
     * mode. In the URL based mode, all the file types are shown but the
     * initial location is selected based on the desired file type.
     * @return The initial URL for the file selector.
     */
    private String getStartUrl() {
        if (currentMode == MODE_API_DEFINED) {
            // API defined
            return FILE_SYSTEMS[fileSystemChoiceGroup.getSelectedIndex()];
        }
        
        // URL based
        final int selectedFileType = fileTypeChoiceGroup.getSelectedIndex();
        
        switch (selectedFileType) {
            case URL_FILE_TYPE_MUSIC:
                return System.getProperty("fileconn.dir.music");
            case URL_FILE_TYPE_PHOTOS:
                return System.getProperty("fileconn.dir.photos");
            case URL_FILE_TYPE_VIDEO:
                return System.getProperty("fileconn.dir.videos");
            default:
                break;
        }
        
        return null;
    }

    /**
     * Resolves the correct API defined index for the selected file type. Note
     * that this method should only be called if the mode is set to
     * MODE_API_DEFINED.
     * @return The API defined index for the selected file type.
     */
    private int getMediaType() {
        final int selectedFileType = fileTypeChoiceGroup.getSelectedIndex();
        
        switch (selectedFileType) {
            case API_FILE_TYPE_ALL:
                return FileSelect.MEDIA_TYPE_ALL;
            case API_FILE_TYPE_PICTURE:
                return FileSelect.MEDIA_TYPE_PICTURE;
            case API_FILE_TYPE_AUDIO:
                return FileSelect.MEDIA_TYPE_AUDIO;
            case API_FILE_TYPE_VIDEO:
                return FileSelect.MEDIA_TYPE_VIDEO;
            case API_FILE_TYPE_APPLICATION:
                return FileSelect.MEDIA_TYPE_APPLICATION;
            default:
                break;
        }
        
        return FileSelect.MEDIA_TYPE_ALL;
    }
}