com.motorola.studio.android.launch.ui.LaunchConfigurationTab.java Source code

Java tutorial

Introduction

Here is the source code for com.motorola.studio.android.launch.ui.LaunchConfigurationTab.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.launch.ui;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
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.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.sequoyah.device.framework.events.IInstanceListener;
import org.eclipse.sequoyah.device.framework.events.InstanceEvent;
import org.eclipse.sequoyah.device.framework.events.InstanceEventManager;
import org.eclipse.sequoyah.device.framework.model.IInstance;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.plugin.AbstractUIPlugin;

import com.android.ide.eclipse.adt.io.IFolderWrapper;
import com.android.sdklib.xml.AndroidManifestParser;
import com.android.sdklib.xml.ManifestData;
import com.android.sdklib.xml.ManifestData.Activity;
import com.motorola.studio.android.adt.ISerialNumbered;
import com.motorola.studio.android.adt.SdkUtils;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.emulator.device.handlers.OpenNewDeviceWizardHandler;
import com.motorola.studio.android.emulator.device.refresh.InstancesListRefresh;
import com.motorola.studio.android.launch.ILaunchConfigurationConstants;
import com.motorola.studio.android.launch.LaunchPlugin;
import com.motorola.studio.android.launch.LaunchUtils;
import com.motorola.studio.android.launch.i18n.LaunchNLS;

/**
 * DESCRIPTION: This class implements the tab that is shown when the user is
 * editing the configuration to run a MOTODEV Studio for Android application
 * 
 * RESPONSIBILITY: User interface to allow the user to enter information to
 * launch the application.
 * 
 * COLABORATORS: This class is one of the tabs of the
 * LaunchConfigurationTabGroup
 * 
 * USAGE: This class should be created/used by the LaunchConfigurationTabGroup
 * only.
 */
@SuppressWarnings("restriction")
public class LaunchConfigurationTab extends AbstractLaunchConfigurationTab {
    private static final String NAME = LaunchNLS.UI_LaunchConfigurationTab_Tab_Name;

    private static final Object UPDATE_WIDGETS_EVENT = new Object();

    private Composite mainComposite;

    private String projectName = ""; //$NON-NLS-1$

    private String activityName = ""; //$NON-NLS-1$

    private String deviceName = ""; //$NON-NLS-1$

    private boolean activitySpecified = false;

    private boolean runDefaultActivity = true;

    private final String LAUNCH_DIALOG_HELP = LaunchPlugin.PLUGIN_ID + ".mainLaunchTab"; //$NON-NLS-1$

    private Button defaultLauncherButton = null;

    private Button vdlLauncherButton = null;

    private Button deviceNameBrowseButton = null;

    private final IInstanceListener instanceListener = new IInstanceListener() {

        private void fireUpdate() {
            Display currentDisplay = PlatformUI.getWorkbench().getDisplay();
            if (!currentDisplay.isDisposed()) {
                currentDisplay.syncExec(new Runnable() {

                    public void run() {
                        updateDeviceChooserButton();
                        updateLaunchConfigurationDialog();
                    }
                });
            }
        }

        public void instanceUpdated(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceUnloaded(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceTransitioned(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceLoaded(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceDeleted(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceCreated(InstanceEvent instanceevent) {
            fireUpdate();
        }

        public void instanceAboutToTransition(InstanceEvent instanceevent) {
            fireUpdate();
        }
    };

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        Composite main = new Composite(parent, SWT.NONE);

        GridLayout layout = new GridLayout(1, false);
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd.widthHint = 430;
        gd.heightHint = 130;
        main.setLayout(layout);
        main.setLayoutData(gd);

        createMainInfoGroup(main);
        setControl(main);
    }

    private void updateDeviceChooserButton() {
        // button is always enabled
        if (!deviceNameBrowseButton.isDisposed()) {
            deviceNameBrowseButton.setEnabled(true);
        }
    }

    /**
     * Create the main information selection group
     * @param mainComposite: the parent composite
     */
    private void createMainInfoGroup(Composite mainComposite) {
        this.mainComposite = mainComposite;

        // create destination group
        Group destinationGroup = new Group(mainComposite, SWT.NONE);
        GridLayout layout = new GridLayout(3, false);
        destinationGroup.setLayout(layout);
        GridData defaultDestGridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
        destinationGroup.setLayoutData(defaultDestGridData);
        destinationGroup.setText(LaunchNLS.LaunchComposite_UI_LaunchComposite_DestinationGroupText);

        // Project Name Label
        Label projectNameLabel = new Label(destinationGroup, SWT.NONE);
        projectNameLabel.setText(LaunchNLS.UI_LaunchComposite_ProjectNameLabel);
        GridData folderGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        projectNameLabel.setLayoutData(folderGridData);

        // Project Name Text 
        final Text projectNameText = new Text(destinationGroup, SWT.SINGLE | SWT.BORDER);
        projectNameText.setText(projectName);
        folderGridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
        projectNameText.setLayoutData(folderGridData);
        projectNameText.addModifyListener(new ModifyListener() {
            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
             */
            public void modifyText(ModifyEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    projectNameText.setText(projectName);
                } else {
                    projectName = projectNameText.getText();
                    updateLaunchConfigurationDialog();
                }
            }
        });

        // Project Name Browse Button
        Button projectNameBrowseButton = new Button(destinationGroup, SWT.PUSH);
        folderGridData = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
        projectNameBrowseButton.setLayoutData(folderGridData);
        projectNameBrowseButton.setText(LaunchNLS.UI_LaunchComposite_BrowseButton);
        projectNameBrowseButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                AndroidProjectsSelectionDialog dialog = new AndroidProjectsSelectionDialog(getShell());
                int result = dialog.open();
                if (result == Dialog.OK) {
                    Object resultProject = dialog.getFirstResult();
                    if (resultProject instanceof IProject) {
                        IProject project = (IProject) resultProject;
                        projectNameText.setText(project.getName());
                    }
                }
            }

        });

        Group activityGroup = new Group(mainComposite, SWT.NONE);
        GridLayout activityLayout = new GridLayout(3, false);
        activityGroup.setLayout(activityLayout);
        GridData activityGrid = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
        activityGroup.setLayoutData(activityGrid);
        activityGroup.setText(LaunchNLS.UI_LaunchComposite_ActivityGroupLabel);

        final Button defaultActivityButton = new Button(activityGroup, SWT.RADIO);
        defaultActivityButton.setText(LaunchNLS.UI_LaunchComposite_ActivityDefaultButton);
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.horizontalSpan = 3;
        defaultActivityButton.setLayoutData(gridData);

        // Activity Name Button
        final Button specificActivityButton = new Button(activityGroup, SWT.RADIO);
        specificActivityButton.setText(LaunchNLS.LaunchConfigurationTab_LaunchButton);
        GridData activityData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        specificActivityButton.setLayoutData(activityData);

        // Activity Name Text 
        final Text activityNameText = new Text(activityGroup, SWT.SINGLE | SWT.BORDER);
        activityNameText.setText(activityName);
        activityData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
        activityNameText.setLayoutData(activityData);
        activityNameText.addModifyListener(new ModifyListener() {
            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
             */
            public void modifyText(ModifyEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    activityNameText.setText(activityName);
                } else {
                    activityName = activityNameText.getText();
                    updateLaunchConfigurationDialog();
                }
            }
        });

        // Activity Name Browse Button
        final Button activityNameBrowseButton = new Button(activityGroup, SWT.PUSH);
        activityData = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
        activityNameBrowseButton.setLayoutData(activityData);
        activityNameBrowseButton.setText(LaunchNLS.UI_LaunchComposite_BrowseButton);
        activityNameBrowseButton.addSelectionListener(new SelectionAdapter() {
            /**
             * Retrieve all activities of a given project
             * @return All the activities of a given project
             */
            private Set<String> getAllActivities(String projectName) {
                String[] tempActivities = null;
                Set<String> activities = new HashSet<String>();

                if (projectName.length() != 0) {
                    IProject selectedProject = LaunchUtils.getProject(projectName);

                    tempActivities = LaunchUtils.getProjectActivities(selectedProject);
                    for (String s : tempActivities) {
                        activities.add(s);
                    }
                }
                return activities;
            }

            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (projectName.length() == 0) {
                    IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                    MessageDialog.openInformation(ww.getShell(), LaunchNLS.UI_LaunchComposite_ProjectRequiredTitle,
                            LaunchNLS.UI_LaunchComposite_ProjectRequiredMessage);
                } else {

                    ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(),
                            new LabelProvider() {
                                @Override
                                public String getText(Object element) {
                                    String activity = (String) element;
                                    return activity;
                                }
                            }) {
                        /*
                         * (non-Javadoc)
                         * @see org.eclipse.ui.dialogs.ElementListSelectionDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
                         */
                        @Override
                        protected Control createDialogArea(Composite parent) {
                            PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
                                    ACTIVITY_SELECTION_DIALOG_HELPID);
                            return super.createDialogArea(parent);
                        }

                    };

                    dialog.setTitle(LaunchNLS.UI_LaunchComposite_SelectActivityScreenTitle);
                    dialog.setMessage(LaunchNLS.UI_LaunchComposite_SelectActivityScreenMessage);

                    Object[] allActivities = getAllActivities(projectNameText.getText()).toArray();
                    if (allActivities.length == 0) {
                        activityNameText.setText(""); //$NON-NLS-1$
                    } else {
                        dialog.setElements(getAllActivities(projectNameText.getText()).toArray());

                        int buttonId = dialog.open();
                        if (buttonId == IDialogConstants.OK_ID) {
                            String activity = (String) dialog.getFirstResult();
                            activityNameText.setText(activity);

                        }
                    }
                }
            }

            protected static final String ACTIVITY_SELECTION_DIALOG_HELPID = "com.motorola.studio.android.launch.activitySelectionDialog"; //$NON-NLS-1$
        });

        final Button noActivityButton = new Button(activityGroup, SWT.RADIO);
        noActivityButton.setText(LaunchNLS.LaunchConfigurationTab_DoNothingButton);
        gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.horizontalSpan = 3;
        noActivityButton.setLayoutData(gridData);

        defaultActivityButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    defaultActivityButton.setSelection(!activitySpecified && runDefaultActivity);
                    activityNameText.setEnabled(activitySpecified);
                    activityNameBrowseButton.setEnabled(activitySpecified);
                } else {
                    // handle variables
                    handleActivityLauncherTypeVariables(defaultActivityButton, specificActivityButton,
                            activityNameText, activityNameBrowseButton);
                }
            }
        });

        specificActivityButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    specificActivityButton.setSelection(activitySpecified && !runDefaultActivity);
                    activityNameText.setEnabled(activitySpecified);
                    activityNameBrowseButton.setEnabled(activitySpecified);
                } else {
                    // handle variables
                    handleActivityLauncherTypeVariables(defaultActivityButton, specificActivityButton,
                            activityNameText, activityNameBrowseButton);
                }
            }
        });

        noActivityButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    noActivityButton.setSelection(!activitySpecified && !runDefaultActivity);
                    activityNameText.setEnabled(activitySpecified);
                    activityNameBrowseButton.setEnabled(activitySpecified);
                } else {
                    // handle variables
                    handleActivityLauncherTypeVariables(defaultActivityButton, specificActivityButton,
                            activityNameText, activityNameBrowseButton);
                }
            }
        });

        // Device Name Label
        Label deviceNameLabel = new Label(destinationGroup, SWT.NONE);
        deviceNameLabel.setText(LaunchNLS.UI_LaunchComposite_DeviceNameLabel);
        GridData deviceGridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        deviceNameLabel.setLayoutData(deviceGridData);

        // Device Name Text 
        final Text deviceNameText = new Text(destinationGroup, SWT.SINGLE | SWT.BORDER);
        deviceNameText.setText(deviceName);
        deviceGridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
        deviceNameText.setLayoutData(deviceGridData);
        deviceNameText.addModifyListener(new ModifyListener() {
            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
             */
            public void modifyText(ModifyEvent e) {
                if (e.data == UPDATE_WIDGETS_EVENT) {
                    deviceNameText.setText(deviceName);
                } else {
                    deviceName = deviceNameText.getText();
                    updateLaunchConfigurationDialog();
                }
            }
        });

        // Device Name Browse Button
        deviceNameBrowseButton = new Button(destinationGroup, SWT.PUSH);
        deviceGridData = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
        deviceNameBrowseButton.setLayoutData(deviceGridData);
        deviceNameBrowseButton.setText(LaunchNLS.UI_LaunchComposite_BrowseButton);
        deviceNameBrowseButton.addSelectionListener(new SelectionAdapter() {

            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
             */
            @Override
            public void widgetSelected(SelectionEvent e) {
                IProject selectedProject = LaunchUtils.getProject(projectNameText.getText());
                DeviceSelectionDialog dialog = new DeviceSelectionDialog(getShell(),
                        LaunchNLS.UI_LaunchComposite_SelectDeviceScreenMessage, selectedProject);
                dialog.setTitle(LaunchNLS.UI_LaunchComposite_SelectDeviceScreenTitle);
                dialog.setMultipleSelection(false);
                dialog.setValidator(new ISelectionStatusValidator() {

                    public IStatus validate(Object[] selection) {
                        IStatus status = new Status(IStatus.OK, LaunchPlugin.PLUGIN_ID, ""); //$NON-NLS-1$
                        if (selection.length == 0) {
                            status = new Status(IStatus.ERROR, LaunchPlugin.PLUGIN_ID, "No selected instance"); //$NON-NLS-1$
                        }
                        return status;
                    }
                });
                int res = dialog.open();
                if (res == IDialogConstants.OK_ID) {
                    ISerialNumbered serialNumbered = (ISerialNumbered) dialog.getFirstResult();
                    String selectedDevice = ((IInstance) serialNumbered).getName();
                    deviceNameText.setText(selectedDevice);
                }
            }

        });

        InstanceEventManager.getInstance().addInstanceListener(instanceListener);

        Link createNewAvdLink = new Link(destinationGroup, SWT.NONE);
        deviceGridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false, 3, 1);
        createNewAvdLink.setLayoutData(deviceGridData);
        createNewAvdLink.setText(LaunchNLS.LaunchConfigurationTab_CreateNewAVDLink);
        createNewAvdLink.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                OpenNewDeviceWizardHandler handler = new OpenNewDeviceWizardHandler();
                try {
                    handler.execute(new ExecutionEvent());
                } catch (ExecutionException exception) {
                    //do nothing
                }
            }
        });

        mainComposite.addListener(SWT.Modify, new Listener() {
            /*
             * (non-Javadoc)
             * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
             */
            public void handleEvent(Event e) {
                projectNameText.notifyListeners(SWT.Modify, e);
                activityNameText.notifyListeners(SWT.Modify, e);
                deviceNameText.notifyListeners(SWT.Modify, e);
                defaultActivityButton.notifyListeners(SWT.Selection, e);
                specificActivityButton.notifyListeners(SWT.Selection, e);
                noActivityButton.notifyListeners(SWT.Selection, e);

                if (defaultLauncherButton != null) {
                    defaultLauncherButton.notifyListeners(SWT.Selection, e);
                }
                if (vdlLauncherButton != null) {
                    vdlLauncherButton.notifyListeners(SWT.Selection, e);
                }
            }
        });

        PlatformUI.getWorkbench().getHelpSystem().setHelp(mainComposite, LAUNCH_DIALOG_HELP); //$NON-NLS-1$
    }

    /**
     * Handle the variables regarding Activity Launcher options.
     * 
     * @param defaultActivityButton {@link Button} for Default Activity.
     * @param specificActivityButton {@link Button} for Specific Activity.
     * @param activityNameText {@link Text} holding the Activity to be launched name.
     * @param activityNameBrowseButton Activity browser {@link Button}.
     */
    private void handleActivityLauncherTypeVariables(final Button defaultActivityButton,
            final Button specificActivityButton, final Text activityNameText,
            final Button activityNameBrowseButton) {
        activitySpecified = specificActivityButton.getSelection();
        runDefaultActivity = defaultActivityButton.getSelection();
        activityNameText.setEnabled(activitySpecified);
        activityNameBrowseButton.setEnabled(activitySpecified);
        updateLaunchConfigurationDialog();
    }

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
     */
    public String getName() {
        return LaunchConfigurationTab.NAME;
    }

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
     */
    @Override
    public Image getImage() {
        return AbstractUIPlugin
                .imageDescriptorFromPlugin(LaunchPlugin.PLUGIN_ID, ILaunchConfigurationConstants.MOTODEV_APP_ICO)
                .createImage();
    }

    @Override
    public void dispose() {
        InstanceEventManager.getInstance().removeInstanceListener(instanceListener);
        super.dispose();
    }

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
     */
    public void initializeFrom(ILaunchConfiguration configuration) {
        // Assure that when loading the configuration, the TmL devices are in sync with the
        // AVD available at the SDK
        InstancesListRefresh.refresh();

        try {
            projectName = configuration.getAttribute(ILaunchConfigurationConstants.ATTR_PROJECT_NAME,
                    ILaunchConfigurationConstants.DEFAULT_VALUE);

            activityName = configuration.getAttribute(ILaunchConfigurationConstants.ATTR_ACTIVITY,
                    ILaunchConfigurationConstants.DEFAULT_VALUE);

            activitySpecified = (configuration.getAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                    ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_ACTIVITY)) == ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_ACTIVITY;

            runDefaultActivity = (configuration.getAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                    ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_ACTIVITY)) == ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_DEFAULT;

            deviceName = configuration.getAttribute(ILaunchConfigurationConstants.ATTR_DEVICE_INSTANCE_NAME,
                    ILaunchConfigurationConstants.DEFAULT_VALUE);

            Event e = new Event();
            e.type = SWT.Modify;
            e.data = UPDATE_WIDGETS_EVENT;
            mainComposite.notifyListeners(SWT.Modify, e);
        } catch (CoreException e) {
            // Do nothing for now
        }
    }

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    public void performApply(ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_ACTIVITY, activityName);

        // For now we are not preventing the device chooser dialog to appear if the user choose a 
        // handset in the device field. However, if the user chooses an AVD, we set the preferred
        // AVD field so that we force the launch to happen in the selected AVD without asking the
        // user.
        Collection<String> validAvds = SdkUtils.getAllValidVmNames();
        if (validAvds.contains(deviceName)) {
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_DEVICE_INSTANCE_NAME, deviceName);
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_ADT_DEVICE_INSTANCE_NAME, deviceName);
        } else {
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_DEVICE_INSTANCE_NAME, deviceName);
            configuration.removeAttribute(ILaunchConfigurationConstants.ATTR_ADT_DEVICE_INSTANCE_NAME);
        }

        if (activitySpecified) {
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                    ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_ACTIVITY);
        } else if (runDefaultActivity) {
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                    ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_DEFAULT);
        } else {
            configuration.setAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                    ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_DO_NOTHING);
        }

        LaunchUtils.updateLaunchConfigurationDefaults(configuration);

        IProject project = LaunchUtils.getProject(projectName);
        IResource[] mappedResources = null;
        if (project != null) {
            mappedResources = new IResource[] { project };
        }

        configuration.setMappedResources(mappedResources);
    }

    /**
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_PROJECT_NAME,
                ILaunchConfigurationConstants.DEFAULT_VALUE);
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_ACTIVITY,
                ILaunchConfigurationConstants.DEFAULT_VALUE);
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION,
                ILaunchConfigurationConstants.ATTR_LAUNCH_ACTION_DEFAULT);
        // It is default not to exist Preferred AVD attribute, so we just set the Studio's 
        // device instance name attribute here
        configuration.setAttribute(ILaunchConfigurationConstants.ATTR_DEVICE_INSTANCE_NAME,
                ILaunchConfigurationConstants.DEFAULT_VALUE);

        LaunchUtils.setADTLaunchConfigurationDefaults(configuration);

        projectName = ILaunchConfigurationConstants.DEFAULT_VALUE; //$NON-NLS-1$
        activityName = ILaunchConfigurationConstants.DEFAULT_VALUE; //$NON-NLS-1$
        deviceName = ILaunchConfigurationConstants.DEFAULT_VALUE; //$NON-NLS-1$
        activitySpecified = ILaunchConfigurationConstants.DEFAULT_BOOL_VALUE;
        runDefaultActivity = !ILaunchConfigurationConstants.DEFAULT_BOOL_VALUE;

        if (mainComposite != null) {
            Event e = new Event();
            e.type = SWT.Modify;
            e.data = UPDATE_WIDGETS_EVENT;
            mainComposite.notifyListeners(SWT.Modify, e);
        }
    }

    /**
     * @see ILaunchConfigurationTab#isValid(ILaunchConfiguration)
     */
    @Override
    public boolean isValid(ILaunchConfiguration launchConfig) {
        boolean isValid = true;
        boolean hasWarning = false;

        String projectName = ""; //$NON-NLS-1$
        String instanceName = ""; //$NON-NLS-1$
        String activityName = ""; //$NON-NLS-1$

        try {
            projectName = launchConfig.getAttribute(ILaunchConfigurationConstants.ATTR_PROJECT_NAME,
                    ILaunchConfigurationConstants.DEFAULT_VALUE);
            instanceName = launchConfig.getAttribute(ILaunchConfigurationConstants.ATTR_DEVICE_INSTANCE_NAME,
                    (String) null);
            activityName = launchConfig.getAttribute(ILaunchConfigurationConstants.ATTR_ACTIVITY,
                    ILaunchConfigurationConstants.DEFAULT_VALUE);
        } catch (CoreException e) {
            StudioLogger.error(LaunchConfigurationTab.class,
                    "Error validating launch configuration " + launchConfig.getName(), e); //$NON-NLS-1$
        }

        /* Validate current project */

        IProject project = null;

        if (isValid && (projectName.length() > 0)) {
            Path projectPath = new Path(projectName);
            if (!projectPath.isValidSegment(projectName)) {
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_PROJECT_NOT_EXIST);
            }
            project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
            if ((project != null) && !project.exists()) {
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_PROJECT_NOT_EXIST);
            } else if ((project != null) && SdkUtils.isLibraryProject(project)) {
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_PROJECT_IS_LIBRARY);
            } else if (project == null) {
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_PROJECT_NOT_EXIST);
            }
        } else if (isValid && (projectName.length() == 0)) {
            setErrorMessage(null);
        }

        // if we have a chosen project, enable/disable the device selection
        if (project != null) {
            updateDeviceChooserButton();
        }

        /* Validate current device instance */
        if (isValid && (instanceName != null) && (instanceName.length() > 0)) {
            IStatus compatible = LaunchUtils.isCompatible(project, instanceName);
            if (compatible == null) {
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_DEVICE_INEXISTENT);
                isValid = false;
            } else if (compatible.getSeverity() == IStatus.ERROR) {
                setErrorMessage(compatible.getMessage());
                isValid = false;
            } else if (compatible.getSeverity() == IStatus.WARNING) {
                setMessage(compatible.getMessage());
                hasWarning = true;
            }
        } else if (isValid && (instanceName != null) && (instanceName.length() == 0)) {
            setErrorMessage(null);
        }

        /* Validate current activity */
        if (isValid && (activityName.length() > 0) && activitySpecified) {
            /*
             * Check if the activity is valid in the current METAINF project
             * file
             */

            Activity[] currentActivities = null;
            boolean activityValid = false;

            ManifestData manifestParser = null;
            try {
                manifestParser = AndroidManifestParser.parse(new IFolderWrapper(project));
            } catch (Exception e) {
                StudioLogger.error(LaunchUtils.class, "An error occurred trying to parse AndroidManifest", e); //$NON-NLS-1$
            }
            if (manifestParser != null) {
                currentActivities = manifestParser.getActivities();
            } else {
                // There's a problem with the manifest file / parser. Invalidate
                // current settings.
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_INVALID_ACTIVITY);
            }

            /* See if the chosen activity is there */

            for (Activity s : currentActivities) {
                if (s.getName().equals(activityName)) {
                    activityValid = true;
                }
            }

            if (!activityValid) {
                isValid = false;
                setErrorMessage(LaunchNLS.UI_LaunchConfigurationTab_ERR_ACTIVITY_NOT_EXIST);
            }

        } else if (isValid && ((activityName.length() == 0) && activitySpecified)) {
            setErrorMessage(null);
        }

        /* Wrap up validation */
        if (isValid && ((projectName.length() == 0) || ((activitySpecified) && (activityName.length() == 0))
                || (instanceName.length() == 0))) {
            isValid = false;

            if (projectName.length() == 0) {
                setMessage(LaunchNLS.UI_LaunchConfigurationTab_InfoSelectProject);
            } else if (instanceName.length() == 0) {
                setMessage(LaunchNLS.UI_LaunchConfigurationTab_InfoSelectInstance);
            } else if (activityName.length() == 0) {
                setMessage(LaunchNLS.UI_LaunchConfigurationTab_InfoSelectActivity);
            }

        }

        if (isValid) {
            setErrorMessage(null);
            if (!hasWarning) {
                setMessage(null);
            }
        }

        return isValid;
    }
}