com.motorola.studio.android.generatemenucode.ui.GenerateMenuCodeDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.motorola.studio.android.generatemenucode.ui.GenerateMenuCodeDialog.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.motorola.studio.android.generatemenucode.ui;

import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

import com.motorola.studio.android.codeutils.CodeUtilsActivator;
import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS;
import com.motorola.studio.android.common.IAndroidConstants;
import com.motorola.studio.android.common.exception.AndroidException;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.generatecode.JDTUtils;
import com.motorola.studio.android.generatemenucode.model.codegenerators.CodeGeneratorDataBasedOnMenu;
import com.motorola.studio.android.generatemenucode.model.codegenerators.JavaModifierBasedOnMenu;

/**
 * Dialog to generate code to deal with Android menus base on a selected menu.xml file
 */
public class GenerateMenuCodeDialog extends TitleAreaDialog {

    private ICompilationUnit javaFile;

    private IProject javaProject = null;

    private JavaModifierBasedOnMenu modifier;

    private Combo projectNameComboBox;

    private Combo classNameComboBox;

    private Combo menuFileNameComboBox;

    private String menuFileErrorMessage;

    private final String helpID = CodeUtilsActivator.PLUGIN_ID + ".generate-code-from-context-menu-dialog"; //$NON-NLS-1$

    private Image image = null;

    private List<IType> availableFragmentClasses = null;

    private final String defaultMessage;

    private final String title;

    private final String shellTitle;

    /**
     * Default constructor for the dialog
     * @param parentShell shell to open the dialog
     * @param description text to show dialog
     * @param title text
     * @param shellTitle window text
     * @param image icon to show in the dialog
     */
    public GenerateMenuCodeDialog(Shell parentShell, String description, String title, String shellTitle,
            Image image) {
        super(parentShell);
        this.defaultMessage = description != null ? description : ""; //$NON-NLS-1$
        this.title = title != null ? title : ""; //$NON-NLS-1$
        this.shellTitle = shellTitle != null ? shellTitle : ""; //$NON-NLS-1$
        this.image = image;
    }

    /**
     * Set the initial values for project name and class name, if there is some selected.
     * Also, set the modifier that will be used to generate code - the dialog set its codeGeneratorData
     * according to the selected menu.
     * @param modifier modifier that will have its codeGeneratorData set
     * @param javaProject the project that will be selected when the dialog appears
     * @param javaFile the class that will be selected when the dialog appears
     * */
    public void init(JavaModifierBasedOnMenu modifier, IProject javaProject, IFile javaFile) {
        setJavaModifier(modifier);
        setJavaProject(javaProject);
        setJavaFile(javaFile);
    }

    @Override
    protected Control createContents(Composite parent) {
        Control c = super.createContents(parent);
        setTitle(title);
        if (image != null) {
            setTitleImage(image);
        }
        validate();
        return c;
    }

    @Override
    protected final Control createDialogArea(Composite parent) {
        if (helpID != null) {
            PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, helpID);
        }
        Composite parentComposite = (Composite) super.createDialogArea(parent);
        Composite mainComposite = new Composite(parentComposite, SWT.NULL);
        mainComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
        mainComposite.setLayout(new GridLayout(2, false));
        createProjectNameArea(mainComposite);
        createClassNameArea(mainComposite);
        createMenuFileNameArea(mainComposite);

        Label separator = new Label(mainComposite, SWT.SEPARATOR | SWT.HORIZONTAL);
        separator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));

        return parentComposite;

    }

    /**
     * Create GUI items for project name selection.
     * @param optionsComposite
     */
    private void createProjectNameArea(Composite parent) {
        Label projectLabel = new Label(parent, SWT.NONE);
        projectLabel.setText(CodeUtilsNLS.GenerateMenuCodeDialog_ProjectLabel);
        projectLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));

        projectNameComboBox = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
        projectNameComboBox.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
        projectNameComboBox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                setJavaProject((IProject) projectNameComboBox.getData(projectNameComboBox.getText()));
                populateClasses();
                populateMenuFileNames();
            }
        });
        populateProjects();
    }

    /**
     * Create GUI items for class name selection.
     * @param parent
     */
    private void createClassNameArea(Composite parent) {
        Label classLabel = new Label(parent, SWT.NONE);
        classLabel.setText(CodeUtilsNLS.GenerateMenuCodeDialog_TargetClassLabel);
        classLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));

        classNameComboBox = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
        classNameComboBox.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
        classNameComboBox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                setJavaFile(((IType) classNameComboBox.getData(classNameComboBox.getText())).getCompilationUnit());
                populateMenuFileNames();
            }
        });
        populateClasses();
    }

    /**
     * Create GUI items for layout file name selection.
     * @param parent
     */
    private void createMenuFileNameArea(Composite parent) {
        Label menuFileLabel = new Label(parent, SWT.NONE);
        menuFileLabel.setText(CodeUtilsNLS.GenerateMenuCodeDialog_MenuFileLabel);
        menuFileLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));

        menuFileNameComboBox = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
        menuFileNameComboBox.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));

        menuFileNameComboBox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                validateMenuFileNames(menuFileNameComboBox.getText());
            }
        });
        populateMenuFileNames();

    }

    /**
     * Populate the combobox that holds projects, with information gathered from the ResourcesPlugin.
     * also selects the project set in the init method
     */
    private void populateProjects() {
        if (projectNameComboBox != null) {
            IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
            int i = 0, selectedProjectIndex = -1;

            for (IProject prj : projects) {
                try {
                    if (prj.hasNature(IAndroidConstants.ANDROID_NATURE)) {
                        projectNameComboBox.add(prj.getName());
                        projectNameComboBox.setData(prj.getName(), prj);
                        if ((javaProject != null) && prj.equals(javaProject)) {
                            selectedProjectIndex = i;
                        }
                        i++;
                    }
                } catch (CoreException e) {
                    StudioLogger.info("Project nature could not be checked."); //$NON-NLS-1$
                }
            }

            if (projectNameComboBox.getItemCount() > 0) {
                if (selectedProjectIndex == -1) {
                    projectNameComboBox.select(0);
                    setJavaProject((IProject) projectNameComboBox.getData(projectNameComboBox.getText()));
                } else {
                    projectNameComboBox.select(selectedProjectIndex);
                }
            }

        }
        validate();
    }

    /**
     * Populate the combobox that holds class names. 
     */
    private void populateClasses() {
        if (classNameComboBox != null) {
            classNameComboBox.removeAll();
            if (javaProject != null) {
                int i = 0, selectedTypeIndex = -1;
                try {
                    List<IType> availableClasses = JDTUtils.getAvailableActivities(javaProject,
                            new NullProgressMonitor());

                    //Fragment classes can have menu too, so add all fragment classes to menu combo box

                    if (availableFragmentClasses != null) {
                        availableFragmentClasses.clear();
                    }
                    availableFragmentClasses = JDTUtils.getAvailableFragmentsSubclasses(
                            (IProject) projectNameComboBox.getData(projectNameComboBox.getText()),
                            new NullProgressMonitor());

                    availableClasses.addAll(availableFragmentClasses);

                    for (IType availableClass : availableClasses) {
                        classNameComboBox.add(availableClass.getFullyQualifiedName());
                        classNameComboBox.setData(availableClass.getFullyQualifiedName(), availableClass);
                        if ((getJavaFile() != null) && availableClass.getCompilationUnit().equals(getJavaFile())) {
                            selectedTypeIndex = i;
                        }
                        i++;
                    }
                    if (classNameComboBox.getItemCount() > 0) {
                        if (selectedTypeIndex == -1) {
                            classNameComboBox.select(0);
                            setJavaFile(((IType) classNameComboBox.getData(classNameComboBox.getText()))
                                    .getCompilationUnit());
                        } else {
                            classNameComboBox.select(selectedTypeIndex);
                        }
                    }
                } catch (JavaModelException e) {
                    StudioLogger.info("Could not get available classes for the selected project"); //$NON-NLS-1$
                }

                classNameComboBox.setEnabled(classNameComboBox.getItemCount() > 0);
            }
        }
        validate();
    }

    /**
     * Validate the selected menu file of the combobox that holds menu file names. 
     */
    protected void validateMenuFileNames(String menuFileName) {
        menuFileErrorMessage = null;

        if ((menuFileNameComboBox != null) && (menuFileNameComboBox.getData(menuFileName) instanceof String)) {
            // If the data type is a String, it represents an error message.
            menuFileErrorMessage = (String) menuFileNameComboBox.getData(menuFileName);
        }

        validate();
    }

    /**
     * Populate the combobox that holds menu file names. 
     */
    private void populateMenuFileNames() {
        if ((menuFileNameComboBox != null) && (getJavaFile() != null)) {
            menuFileNameComboBox.removeAll();
            menuFileErrorMessage = null;
            CompilationUnit cpAstNode = JDTUtils.parse(getJavaFile());
            if (!JDTUtils.hasErrorInCompilationUnitAstUtils(cpAstNode)) {
                IProject prj = (IProject) this.projectNameComboBox.getData(this.projectNameComboBox.getText());

                IFolder menuFolder = prj.getFolder(IAndroidConstants.FD_RESOURCES)
                        .getFolder(IAndroidConstants.FD_MENU);

                String inflatedMenu = JDTUtils.getInflatedMenuFileName(getJavaProject(), getJavaFile());

                if ((inflatedMenu != null) && (inflatedMenu.length() > 0)) {
                    //the activity/fragment already inflates a menu
                    //select this menu on the combo box
                    try {
                        inflatedMenu = inflatedMenu + '.' + IAndroidConstants.MENU_FILE_EXTENSION;
                        menuFileNameComboBox.add(inflatedMenu);
                        CodeGeneratorDataBasedOnMenu codeGeneratorData;
                        codeGeneratorData = JDTUtils.createMenuFile(getJavaProject(), getJavaFile(), inflatedMenu,
                                getTypeAssociatedToJavaFile());

                        menuFileNameComboBox.setData(inflatedMenu, codeGeneratorData);
                        menuFileNameComboBox.select(0);

                        setMessage(CodeUtilsNLS.GenerateMenuCodeDialog_InflatedMessage, IMessageProvider.NONE);

                    } catch (AndroidException e) {
                        menuFileErrorMessage = e.getMessage();
                        menuFileNameComboBox.setData(inflatedMenu, menuFileErrorMessage);
                    }

                    //Disable the menu combo box so the user cannot change the menu file
                    menuFileNameComboBox.select(0);
                    menuFileNameComboBox.setEnabled(false);
                } else {
                    //there is no inflated menu

                    setMessage(defaultMessage, IMessageProvider.NONE);
                    //iterate over all files inside res/menu
                    try {
                        for (IResource menuFile : menuFolder.members()) {
                            //only consider xml files
                            if ((menuFile.getType() == IResource.FILE)
                                    && menuFile.getFileExtension().equals(IAndroidConstants.MENU_FILE_EXTENSION)) {

                                menuFileNameComboBox.add(menuFile.getName());

                                try {
                                    CodeGeneratorDataBasedOnMenu codeGeneratorData = JDTUtils.createMenuFile(
                                            getJavaProject(), getJavaFile(), menuFile.getName(),
                                            getTypeAssociatedToJavaFile());

                                    menuFileNameComboBox.setData(menuFile.getName(), codeGeneratorData);
                                }

                                catch (AndroidException e) {
                                    // The malformed xml files
                                    menuFileErrorMessage = e.getMessage();
                                    menuFileNameComboBox.setData(menuFile.getName(), menuFileErrorMessage);
                                }

                            }
                        }
                    } catch (CoreException e) {
                        menuFileErrorMessage = CodeUtilsNLS.GenerateMenuCodeDialog_Error_MenuFolderDoesNotExist;
                    }

                    menuFileNameComboBox.select(0); //if the combo box is empty, the selection is ignored 
                    menuFileNameComboBox.setEnabled(menuFileNameComboBox.getItemCount() > 0);
                }
            } else {
                menuFileErrorMessage = CodeUtilsNLS.GenerateMenuCodeDialog_Class_Error;
                this.javaFile = null;
                menuFileNameComboBox.setEnabled(false);
            }
        } else {
            menuFileNameComboBox.setEnabled(false);
        }
        validate();
    }

    /**
     * Retrieve the type ACTIVITY/FRAGMENT from the android class
     * @return
     */
    private CodeGeneratorDataBasedOnMenu.TYPE getTypeAssociatedToJavaFile() {
        CodeGeneratorDataBasedOnMenu.TYPE type = CodeGeneratorDataBasedOnMenu.TYPE.ACTIVITY;
        for (IType availableClass : availableFragmentClasses) {
            if (availableClass.getCompilationUnit().equals(getJavaFile())) {
                type = CodeGeneratorDataBasedOnMenu.TYPE.FRAGMENT;
                break;
            }
        }
        return type;
    }

    @Override
    protected void configureShell(Shell newShell) {
        newShell.setSize(640, 280);
        newShell.setText(shellTitle);
        super.configureShell(newShell);
    }

    /**
     * Validate the UI
     * @return
     */
    protected void validate() {

        String errorMessage = null;

        if ((projectNameComboBox != null) && (projectNameComboBox.getItemCount() == 0)) {
            errorMessage = CodeUtilsNLS.GenerateMenuCodeDialog_NoSuitableProjects;
        }
        if ((errorMessage == null) && (classNameComboBox != null) && (classNameComboBox.getItemCount() == 0)) {
            errorMessage = CodeUtilsNLS.GenerateMenuCodeDialog_NoSuitableClasses;
        }
        if ((errorMessage == null) && (menuFileNameComboBox != null)) {
            if ((menuFileErrorMessage != null) && (menuFileNameComboBox.getSelectionIndex() >= 0)
                    && (menuFileNameComboBox.getData(menuFileNameComboBox
                            .getItem(menuFileNameComboBox.getSelectionIndex())) instanceof String)) {
                errorMessage = (String) menuFileNameComboBox
                        .getData(menuFileNameComboBox.getItem(menuFileNameComboBox.getSelectionIndex()));
            } else {
                if ((menuFileNameComboBox.getItemCount() == 0) && (getJavaFile() != null)) {
                    errorMessage = CodeUtilsNLS.GenerateMenuCodeDialog_NoSuitableMenus;
                } else if (getJavaFile() == null) {
                    errorMessage = menuFileErrorMessage;
                }
            }
        }

        this.setMessage(errorMessage, IMessageProvider.ERROR);

        if (errorMessage == null) {
            if ((this.getMessage() == null) || (this.getMessage().length() == 0)) {
                this.setMessage(defaultMessage, IMessageProvider.NONE);
            }
        }

        if (getButton(OK) != null) {
            getButton(OK).setEnabled((getErrorMessage() == null)
                    || ((getErrorMessage() != null) && (getErrorMessage().trim().isEmpty())));
        }
    }

    private void setJavaFile(IFile javaFile) {
        if (javaFile != null) {
            setJavaFile(JavaCore.createCompilationUnitFrom(javaFile));
        }
    }

    private void setJavaFile(ICompilationUnit javaFile) {
        this.javaFile = javaFile;
        setJavaProject(javaFile.getJavaProject().getProject());
    }

    /**
     * @return Compilation unit for the selected file (activity or fragment)
     */
    public ICompilationUnit getJavaFile() {
        return this.javaFile;
    }

    private void setJavaProject(IProject javaProject) {
        this.javaProject = javaProject;
    }

    private IProject getJavaProject() {
        return this.javaProject;
    }

    /**
     * Returns CodeGeneratorDataBasedOnMenu according to the selected menu file, or null if no menu is selected.
     * */
    private CodeGeneratorDataBasedOnMenu getCodeGeneratorData() {
        CodeGeneratorDataBasedOnMenu result = null;
        if (menuFileNameComboBox.getSelectionIndex() >= 0) {
            result = (CodeGeneratorDataBasedOnMenu) this.menuFileNameComboBox
                    .getData(menuFileNameComboBox.getText());
        }

        return result;
    }

    /**
     * @return the modifier responsible to modify the source code
     */
    public JavaModifierBasedOnMenu getJavaModifier() {
        return modifier;
    }

    /**
     * @param modifier the modifier to set
     */
    public void setJavaModifier(JavaModifierBasedOnMenu modifier) {
        this.modifier = modifier;
    }

    @Override
    protected void okPressed() {
        modifier.setCodeGeneratorData(getCodeGeneratorData());

        super.okPressed();
    }

    /**
     * Sets the focus of the content area of the dialog
     */
    public void setFocus() {
        this.getContents().setFocus();
    }

    @Override
    protected boolean isResizable() {
        return true;
    }
}