diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java new file mode 100644 index 000000000..c66458fc9 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.android.ide.eclipse.adt.internal.launch; + +import com.android.ide.common.xml.ManifestData; +import com.android.ide.common.xml.ManifestData.Activity; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; +import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper; +import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.IProjectChooserFilter; +import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.NonLibraryProjectOnlyFilter; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +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.jdt.core.IJavaModel; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; +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.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +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.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; + +import java.util.ArrayList; + +/** + * Class for the main launch configuration tab. + */ +public class MainLaunchConfigTab extends AbstractLaunchConfigurationTab { + + /** + * + */ + public static final String LAUNCH_TAB_IMAGE = "mainLaunchTab"; //$NON-NLS-1$ + + protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + protected Text mProjText; + private Button mProjButton; + + private Combo mActivityCombo; + private final ArrayList<Activity> mActivities = new ArrayList<Activity>(); + + private WidgetListener mListener = new WidgetListener(); + + private Button mDefaultActionButton; + private Button mActivityActionButton; + private Button mDoNothingActionButton; + private int mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION; + + private ProjectChooserHelper mProjectChooserHelper; + + /** + * A listener which handles widget change events for the controls in this + * tab. + */ + private class WidgetListener implements ModifyListener, SelectionListener { + + @Override + public void modifyText(ModifyEvent e) { + IProject project = checkParameters(); + loadActivities(project); + setDirty(true); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {/* do nothing */ + } + + @Override + public void widgetSelected(SelectionEvent e) { + Object source = e.getSource(); + if (source == mProjButton) { + handleProjectButtonSelected(); + } else { + checkParameters(); + } + } + } + + public MainLaunchConfigTab() { + } + + protected IProjectChooserFilter getProjectFilter() { + return new NonLibraryProjectOnlyFilter(); + } + + @Override + public void createControl(Composite parent) { + mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(), getProjectFilter()); + + Font font = parent.getFont(); + Composite comp = new Composite(parent, SWT.NONE); + setControl(comp); + GridLayout topLayout = new GridLayout(); + topLayout.verticalSpacing = 0; + comp.setLayout(topLayout); + comp.setFont(font); + createProjectEditor(comp); + createVerticalSpacer(comp, 1); + + // create the combo for the activity chooser + Group group = new Group(comp, SWT.NONE); + group.setText("Launch Action:"); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + group.setLayoutData(gd); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + group.setLayout(layout); + group.setFont(font); + + mDefaultActionButton = new Button(group, SWT.RADIO); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + mDefaultActionButton.setLayoutData(gd); + mDefaultActionButton.setText("Launch Default Activity"); + mDefaultActionButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + // event are received for both selection and deselection, so we only process + // the selection event to avoid doing it twice. + if (mDefaultActionButton.getSelection() == true) { + mLaunchAction = LaunchConfigDelegate.ACTION_DEFAULT; + mActivityCombo.setEnabled(false); + checkParameters(); + } + } + }); + + mActivityActionButton = new Button(group, SWT.RADIO); + mActivityActionButton.setText("Launch:"); + mActivityActionButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + // event are received for both selection and deselection, so we only process + // the selection event to avoid doing it twice. + if (mActivityActionButton.getSelection() == true) { + mLaunchAction = LaunchConfigDelegate.ACTION_ACTIVITY; + mActivityCombo.setEnabled(true); + checkParameters(); + } + } + }); + + mActivityCombo = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY); + gd = new GridData(GridData.FILL_HORIZONTAL); + mActivityCombo.setLayoutData(gd); + mActivityCombo.clearSelection(); + mActivityCombo.setEnabled(false); + mActivityCombo.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + checkParameters(); + } + }); + + mDoNothingActionButton = new Button(group, SWT.RADIO); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + mDoNothingActionButton.setLayoutData(gd); + mDoNothingActionButton.setText("Do Nothing"); + mDoNothingActionButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + // event are received for both selection and deselection, so we only process + // the selection event to avoid doing it twice. + if (mDoNothingActionButton.getSelection() == true) { + mLaunchAction = LaunchConfigDelegate.ACTION_DO_NOTHING; + mActivityCombo.setEnabled(false); + checkParameters(); + } + } + }); + + } + + @Override + public String getName() { + return "Android"; + } + + @Override + public Image getImage() { + return IconFactory.getInstance().getIcon(LAUNCH_TAB_IMAGE); + } + + @Override + public void performApply(ILaunchConfigurationWorkingCopy configuration) { + configuration.setAttribute( + IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, mProjText.getText()); + configuration.setAttribute( + IJavaLaunchConfigurationConstants.ATTR_ALLOW_TERMINATE, true); + + // add the launch mode + configuration.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, mLaunchAction); + + // add the activity + int selection = mActivityCombo.getSelectionIndex(); + if (mActivities != null && selection >=0 && selection < mActivities.size()) { + configuration.setAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, + mActivities.get(selection).getName()); + } + + // link the project and the launch config. + mapResources(configuration); + } + + @Override + public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { + configuration.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, + LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION); + } + + /** + * Creates the widgets for specifying a main type. + * + * @param parent the parent composite + */ + protected void createProjectEditor(Composite parent) { + Font font = parent.getFont(); + Group group = new Group(parent, SWT.NONE); + group.setText("Project:"); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + group.setLayoutData(gd); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + group.setLayout(layout); + group.setFont(font); + mProjText = new Text(group, SWT.SINGLE | SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + mProjText.setLayoutData(gd); + mProjText.setFont(font); + mProjText.addModifyListener(mListener); + mProjButton = createPushButton(group, "Browse...", null); + mProjButton.addSelectionListener(mListener); + } + + /** + * returns the default listener from this class. For all subclasses this + * listener will only provide the functi Jaonality of updating the current + * tab + * + * @return a widget listener + */ + protected WidgetListener getDefaultListener() { + return mListener; + } + + /** + * Return the {@link IJavaProject} corresponding to the project name in the project + * name text field, or null if the text does not match a project name. + * @param javaModel the Java Model object corresponding for the current workspace root. + * @return a IJavaProject object or null. + */ + protected IJavaProject getJavaProject(IJavaModel javaModel) { + String projectName = mProjText.getText().trim(); + if (projectName.length() < 1) { + return null; + } + return javaModel.getJavaProject(projectName); + } + + /** + * Show a dialog that lets the user select a project. This in turn provides + * context for the main type, allowing the user to key a main type name, or + * constraining the search for main types to the specified project. + */ + protected void handleProjectButtonSelected() { + IJavaProject javaProject = mProjectChooserHelper.chooseJavaProject( + mProjText.getText().trim(), + "Please select a project to launch"); + if (javaProject == null) { + return; + }// end if + String projectName = javaProject.getElementName(); + mProjText.setText(projectName); + + // get the list of activities and fill the combo + IProject project = javaProject.getProject(); + loadActivities(project); + }// end handle selected + + /** + * Initializes this tab's controls with values from the given + * launch configuration. This method is called when + * a configuration is selected to view or edit, after this + * tab's control has been created. + * + * @param config launch configuration + * + * @see ILaunchConfigurationTab + */ + @Override + public void initializeFrom(ILaunchConfiguration config) { + String projectName = EMPTY_STRING; + try { + projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, + EMPTY_STRING); + }// end try + catch (CoreException ce) { + } + mProjText.setText(projectName); + + IProject proj = mProjectChooserHelper.getAndroidProject(projectName); + loadActivities(proj); + + // load the launch action. + mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION; + try { + mLaunchAction = config.getAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, + mLaunchAction); + } catch (CoreException e) { + // nothing to be done really. launchAction will keep its default value. + } + + mDefaultActionButton.setSelection(mLaunchAction == LaunchConfigDelegate.ACTION_DEFAULT); + mActivityActionButton.setSelection(mLaunchAction == LaunchConfigDelegate.ACTION_ACTIVITY); + mDoNothingActionButton.setSelection( + mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING); + + // now look for the activity and load it if present, otherwise, revert + // to the current one. + String activityName = EMPTY_STRING; + try { + activityName = config.getAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, EMPTY_STRING); + }// end try + catch (CoreException ce) { + // nothing to be done really. activityName will stay empty + } + + if (mLaunchAction != LaunchConfigDelegate.ACTION_ACTIVITY) { + mActivityCombo.setEnabled(false); + mActivityCombo.clearSelection(); + } else { + mActivityCombo.setEnabled(true); + if (activityName == null || activityName.equals(EMPTY_STRING)) { + mActivityCombo.clearSelection(); + } else if (mActivities != null && mActivities.size() > 0) { + // look for the name of the activity in the combo. + boolean found = false; + for (int i = 0 ; i < mActivities.size() ; i++) { + if (activityName.equals(mActivities.get(i).getName())) { + found = true; + mActivityCombo.select(i); + break; + } + } + + // if we haven't found a matching activity we clear the combo selection + if (found == false) { + mActivityCombo.clearSelection(); + } + } + } + } + + /** + * Associates the launch config and the project. This allows Eclipse to delete the launch + * config when the project is deleted. + * + * @param config the launch config working copy. + */ + protected void mapResources(ILaunchConfigurationWorkingCopy config) { + // get the java model + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + IJavaModel javaModel = JavaCore.create(workspaceRoot); + + // get the IJavaProject described by the text field. + IJavaProject javaProject = getJavaProject(javaModel); + IResource[] resources = null; + if (javaProject != null) { + resources = AndroidLaunchController.getResourcesToMap(javaProject.getProject()); + } + config.setMappedResources(resources); + } + + /** + * Loads the ui with the activities of the specified project, and stores the + * activities in <code>mActivities</code>. + * <p/> + * First activity is selected by default if present. + * + * @param project The project to load the activities from. + */ + private void loadActivities(IProject project) { + if (project != null) { + // parse the manifest for the list of activities. + ManifestData manifestData = AndroidManifestHelper.parseForData(project); + if (manifestData != null) { + Activity[] activities = manifestData.getActivities(); + + mActivities.clear(); + mActivityCombo.removeAll(); + + for (Activity activity : activities) { + if (activity.isExported() && activity.hasAction()) { + mActivities.add(activity); + mActivityCombo.add(activity.getName()); + } + } + + if (mActivities.size() > 0) { + if (mLaunchAction == LaunchConfigDelegate.ACTION_ACTIVITY) { + mActivityCombo.setEnabled(true); + } + } else { + mActivityCombo.setEnabled(false); + } + + // the selection will be set when we update the ui from the current + // config object. + mActivityCombo.clearSelection(); + + return; + } + } + + // if we reach this point, either project is null, or we got an exception during + // the parsing. In either case, we empty the activity list. + mActivityCombo.removeAll(); + mActivities.clear(); + } + + /** + * Checks the parameters for correctness, and update the error message and buttons. + * @return the current IProject of this launch config. + */ + private IProject checkParameters() { + try { + //test the project name first! + String text = mProjText.getText(); + if (text.length() == 0) { + setErrorMessage("Project Name is required!"); + } else if (text.matches("[a-zA-Z0-9_ \\.-]+") == false) { + setErrorMessage("Project name contains unsupported characters!"); + } else { + IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null); + IProject found = null; + for (IJavaProject javaProject : projects) { + if (javaProject.getProject().getName().equals(text)) { + found = javaProject.getProject(); + break; + } + + } + + if (found != null) { + setErrorMessage(null); + } else { + setErrorMessage(String.format("There is no android project named '%1$s'", + text)); + } + + return found; + } + } finally { + updateLaunchConfigurationDialog(); + } + + return null; + } +} |