Home | History | Annotate | Download | only in newproject
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.ide.eclipse.adt.internal.wizards.newproject;
     17 
     18 import com.android.ide.common.xml.ManifestData;
     19 import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
     20 import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper;
     21 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
     22 import com.android.sdklib.IAndroidTarget;
     23 
     24 import org.eclipse.core.resources.IProject;
     25 import org.eclipse.core.resources.IWorkspaceRoot;
     26 import org.eclipse.core.resources.ResourcesPlugin;
     27 import org.eclipse.jdt.core.IJavaModel;
     28 import org.eclipse.jdt.core.IJavaProject;
     29 import org.eclipse.jdt.core.JavaCore;
     30 import org.eclipse.jdt.ui.JavaElementLabelProvider;
     31 import org.eclipse.jface.dialogs.IMessageProvider;
     32 import org.eclipse.jface.viewers.ILabelProvider;
     33 import org.eclipse.jface.wizard.WizardPage;
     34 import org.eclipse.swt.SWT;
     35 import org.eclipse.swt.events.SelectionEvent;
     36 import org.eclipse.swt.events.SelectionListener;
     37 import org.eclipse.swt.layout.GridData;
     38 import org.eclipse.swt.layout.GridLayout;
     39 import org.eclipse.swt.widgets.Button;
     40 import org.eclipse.swt.widgets.Composite;
     41 import org.eclipse.ui.dialogs.FilteredList;
     42 
     43 /**
     44  * Page shown when creating a test project which lets you choose between testing
     45  * yourself and testing a different project
     46  */
     47 class TestTargetPage extends WizardPage implements SelectionListener {
     48     private final NewProjectWizardState mValues;
     49     /** Flag used when setting button/text state manually to ignore listener updates */
     50     private boolean mIgnore;
     51     private String mLastExistingPackageName;
     52 
     53     private Button mCurrentRadioButton;
     54     private Button mExistingRadioButton;
     55     private FilteredList mProjectList;
     56     private boolean mPageShown;
     57 
     58     /**
     59      * Create the wizard.
     60      */
     61     TestTargetPage(NewProjectWizardState values) {
     62         super("testTargetPage"); //$NON-NLS-1$
     63         setTitle("Select Test Target");
     64         setDescription("Choose a project to test");
     65         mValues = values;
     66     }
     67 
     68     /**
     69      * Create contents of the wizard.
     70      */
     71     @Override
     72     public void createControl(Composite parent) {
     73         Composite container = new Composite(parent, SWT.NULL);
     74 
     75         setControl(container);
     76         container.setLayout(new GridLayout(2, false));
     77 
     78         mCurrentRadioButton = new Button(container, SWT.RADIO);
     79         mCurrentRadioButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
     80         mCurrentRadioButton.setText("This project");
     81         mCurrentRadioButton.addSelectionListener(this);
     82 
     83         mExistingRadioButton = new Button(container, SWT.RADIO);
     84         mExistingRadioButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
     85         mExistingRadioButton.setText("An existing Android project:");
     86         mExistingRadioButton.addSelectionListener(this);
     87 
     88         ILabelProvider labelProvider = new JavaElementLabelProvider(
     89                 JavaElementLabelProvider.SHOW_DEFAULT);
     90         mProjectList = new FilteredList(container,
     91                 SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE, labelProvider,
     92                 true /*ignoreCase*/, false /*allowDuplicates*/, true /* matchEmptyString*/);
     93         mProjectList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
     94         mProjectList.addSelectionListener(this);
     95     }
     96 
     97     private void initializeList() {
     98         ProjectChooserHelper helper = new ProjectChooserHelper(getShell(), null /*filter*/);
     99         IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
    100         IJavaModel javaModel = JavaCore.create(workspaceRoot);
    101         IJavaProject[] androidProjects = helper.getAndroidProjects(javaModel);
    102         mProjectList.setElements(androidProjects);
    103         if (mValues.testedProject != null) {
    104             for (IJavaProject project : androidProjects) {
    105                 if (project.getProject() == mValues.testedProject) {
    106                     mProjectList.setSelection(new Object[] { project });
    107                     break;
    108                 }
    109             }
    110         } else {
    111             // No initial selection: force the user to choose
    112             mProjectList.setSelection(new int[0]);
    113         }
    114     }
    115 
    116     @Override
    117     public void setVisible(boolean visible) {
    118         super.setVisible(visible);
    119         mPageShown = true;
    120 
    121         if (visible) {
    122             try {
    123                 mIgnore = true;
    124                 mCurrentRadioButton.setSelection(mValues.testingSelf);
    125                 mExistingRadioButton.setSelection(!mValues.testingSelf);
    126                 mProjectList.setEnabled(!mValues.testingSelf);
    127 
    128                 if (mProjectList.isEmpty()) {
    129                     initializeList();
    130                 }
    131                 if (!mValues.testingSelf) {
    132                     mProjectList.setFocus();
    133                     IProject project = getSelectedProject();
    134                     if (project != null) {
    135                         // The FilteredList seems to -insist- on selecting the first item
    136                         // in the list, even when the selection is explicitly set to an empty
    137                         // array. This means the user is looking at a selection, so we need
    138                         // to also go ahead and select this item in the model such that the
    139                         // two agree, even if we would have preferred to have no initial
    140                         // selection.
    141                         mValues.testedProject = project;
    142                     }
    143                 }
    144             } finally {
    145                 mIgnore = false;
    146             }
    147         }
    148 
    149         validatePage();
    150     }
    151 
    152     @Override
    153     public void widgetSelected(SelectionEvent e) {
    154         if (mIgnore) {
    155             return;
    156         }
    157 
    158         Object source = e.getSource();
    159         if (source == mExistingRadioButton) {
    160             mProjectList.setEnabled(true);
    161             mValues.testingSelf = false;
    162             setExistingProject(getSelectedProject());
    163             mProjectList.setFocus();
    164         } else if (source == mCurrentRadioButton) {
    165             mProjectList.setEnabled(false);
    166             mValues.testingSelf = true;
    167             mValues.testedProject = null;
    168         } else {
    169             // The event must be from the project list, which unfortunately doesn't
    170             // pass itself as the selection event, it passes a reference to some internal
    171             // table widget that it uses, so we check for this case last
    172             IProject project = getSelectedProject();
    173             if (project != mValues.testedProject) {
    174                 setExistingProject(project);
    175             }
    176         }
    177 
    178         validatePage();
    179     }
    180 
    181     private IProject getSelectedProject() {
    182         Object[] selection = mProjectList.getSelection();
    183         IProject project = selection != null && selection.length == 1
    184             ? ((IJavaProject) selection[0]).getProject() : null;
    185         return project;
    186     }
    187 
    188     @Override
    189     public void widgetDefaultSelected(SelectionEvent e) {
    190     }
    191 
    192     private void setExistingProject(IProject project) {
    193         mValues.testedProject = project;
    194 
    195         // Try to update the application, package, sdk target and minSdkVersion accordingly
    196         if (project != null &&
    197                 (!mValues.applicationNameModifiedByUser ||
    198                  !mValues.packageNameModifiedByUser     ||
    199                  !mValues.targetModifiedByUser          ||
    200                  !mValues.minSdkModifiedByUser)) {
    201             ManifestData manifestData = AndroidManifestHelper.parseForData(project);
    202             if (manifestData != null) {
    203                 String appName = String.format("%1$sTest", project.getName());
    204                 String packageName = manifestData.getPackage();
    205                 String minSdkVersion = manifestData.getMinSdkVersionString();
    206                 IAndroidTarget sdkTarget = null;
    207                 if (Sdk.getCurrent() != null) {
    208                     sdkTarget = Sdk.getCurrent().getTarget(project);
    209                 }
    210 
    211                 if (packageName == null) {
    212                     packageName = "";  //$NON-NLS-1$
    213                 }
    214                 mLastExistingPackageName = packageName;
    215 
    216                 if (!mValues.projectNameModifiedByUser) {
    217                     mValues.projectName = appName;
    218                 }
    219 
    220                 if (!mValues.applicationNameModifiedByUser) {
    221                     mValues.applicationName = appName;
    222                 }
    223 
    224                 if (!mValues.packageNameModifiedByUser) {
    225                     packageName += ".test";  //$NON-NLS-1$
    226                     mValues.packageName = packageName;
    227                 }
    228 
    229                 if (!mValues.targetModifiedByUser && sdkTarget != null) {
    230                     mValues.target = sdkTarget;
    231                 }
    232 
    233                 if (!mValues.minSdkModifiedByUser) {
    234                     if (minSdkVersion != null || sdkTarget != null) {
    235                         mValues.minSdk = minSdkVersion;
    236                     }
    237                     if (sdkTarget == null) {
    238                         mValues.updateSdkTargetToMatchMinSdkVersion();
    239                     }
    240                 }
    241             }
    242         }
    243 
    244         updateTestTargetPackageField(mLastExistingPackageName);
    245     }
    246 
    247     /**
    248      * Updates the test target package name
    249      *
    250      * When using the "self-test" option, the packageName argument is ignored and the
    251      * current value from the project package is used.
    252      *
    253      * Otherwise the packageName is used if it is not null.
    254      */
    255     private void updateTestTargetPackageField(String packageName) {
    256         if (mValues.testingSelf) {
    257             mValues.testTargetPackageName = mValues.packageName;
    258         } else if (packageName != null) {
    259             mValues.testTargetPackageName = packageName;
    260         }
    261     }
    262 
    263     @Override
    264     public boolean isPageComplete() {
    265         // Ensure that the user sees the page and makes a selection
    266         if (!mPageShown) {
    267             return false;
    268         }
    269 
    270         return super.isPageComplete();
    271     }
    272 
    273     private void validatePage() {
    274         String error = null;
    275 
    276         if (!mValues.testingSelf) {
    277             if (mValues.testedProject == null) {
    278                 error = "Please select an existing Android project as a test target.";
    279             } else if (mValues.projectName.equals(mValues.testedProject.getName())) {
    280                 error = "The main project name and the test project name must be different.";
    281             }
    282         }
    283 
    284         // -- update UI & enable finish if there's no error
    285         setPageComplete(error == null);
    286         if (error != null) {
    287             setMessage(error, IMessageProvider.ERROR);
    288         } else {
    289             setErrorMessage(null);
    290             setMessage(null);
    291         }
    292     }
    293 }
    294