Home | History | Annotate | Download | only in welcome
      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.welcome;
     17 
     18 import com.android.ide.eclipse.adt.AdtPlugin;
     19 import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
     20 
     21 import org.eclipse.jface.dialogs.IMessageProvider;
     22 import org.eclipse.jface.wizard.WizardPage;
     23 import org.eclipse.swt.SWT;
     24 import org.eclipse.swt.events.ModifyEvent;
     25 import org.eclipse.swt.events.ModifyListener;
     26 import org.eclipse.swt.events.SelectionEvent;
     27 import org.eclipse.swt.events.SelectionListener;
     28 import org.eclipse.swt.layout.GridData;
     29 import org.eclipse.swt.layout.GridLayout;
     30 import org.eclipse.swt.widgets.Button;
     31 import org.eclipse.swt.widgets.Composite;
     32 import org.eclipse.swt.widgets.DirectoryDialog;
     33 import org.eclipse.swt.widgets.Label;
     34 import org.eclipse.swt.widgets.Text;
     35 
     36 import java.io.File;
     37 import java.util.concurrent.atomic.AtomicReference;
     38 
     39 /** Main page shown in the {@link WelcomeWizard} */
     40 public class WelcomeWizardPage extends WizardPage implements ModifyListener, SelectionListener {
     41     private Text mExistingDirText;
     42     private Button mExistingDirButton;
     43     private Button mInstallLatestCheckbox;
     44     private Button mInstallCommonCheckbox;
     45     private Button mInstallNewRadio;
     46     private Button mUseExistingRadio;
     47     private Text mNewDirText;
     48     private Button mNewDirButton;
     49 
     50     /**
     51      * Create the wizard.
     52      */
     53     public WelcomeWizardPage() {
     54         super("welcomePage");
     55         setTitle("Welcome to Android Development");
     56         setDescription("Configure SDK");
     57     }
     58 
     59     /**
     60      * Create contents of the wizard.
     61      * @param parent parent widget to add page to
     62      */
     63     @Override
     64     @SuppressWarnings("unused") // SWT constructors have side effects so "new Label" is not unused
     65     public void createControl(Composite parent) {
     66         Composite container = new Composite(parent, SWT.NULL);
     67 
     68         setControl(container);
     69         container.setLayout(new GridLayout(4, false));
     70 
     71         Label overviewLabel = new Label(container, SWT.WRAP | SWT.SHADOW_NONE);
     72         GridData gdOverviewLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 4, 1);
     73         gdOverviewLabel.widthHint = 580;
     74         overviewLabel.setLayoutData(gdOverviewLabel);
     75         overviewLabel.setText("To develop for Android, you need an Android SDK, and at least one version of the Android APIs to compile against. You may also want additional versions of Android to test with.");
     76 
     77         Label spacing = new Label(container, SWT.NONE);
     78         spacing.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
     79 
     80         mInstallNewRadio = new Button(container, SWT.RADIO);
     81         mInstallNewRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
     82         mInstallNewRadio.setSelection(true);
     83         mInstallNewRadio.setText("Install new SDK");
     84         mInstallNewRadio.addSelectionListener(this);
     85 
     86         Label indentLabel = new Label(container, SWT.NONE);
     87         GridData gdIndentLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
     88         gdIndentLabel.widthHint = 20;
     89         indentLabel.setLayoutData(gdIndentLabel);
     90 
     91         mInstallLatestCheckbox = new Button(container, SWT.CHECK);
     92         mInstallLatestCheckbox.setSelection(true);
     93         mInstallLatestCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3,
     94                 1));
     95         mInstallLatestCheckbox.setText("Install the latest available version of Android APIs (supports all the latest features)");
     96         mInstallLatestCheckbox.addSelectionListener(this);
     97 
     98         new Label(container, SWT.NONE);
     99         mInstallCommonCheckbox = new Button(container, SWT.CHECK);
    100         mInstallCommonCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3,
    101                 1));
    102         mInstallCommonCheckbox.setText("Install Android 2.2, a version which is supported by ~96% phones and tablets");
    103         mInstallCommonCheckbox.addSelectionListener(this);
    104 
    105         new Label(container, SWT.NONE);
    106         Label addHintLabel = new Label(container, SWT.NONE);
    107         addHintLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
    108         addHintLabel.setText("     (You can add additional platforms using the SDK Manager.)");
    109 
    110         new Label(container, SWT.NONE);
    111         Label targetLabel = new Label(container, SWT.NONE);
    112         targetLabel.setText("Target Location:");
    113 
    114         mNewDirText = new Text(container, SWT.BORDER);
    115         mNewDirText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    116         String defaultPath = System.getProperty("user.home") + File.separator + "android-sdks"; //$NON-NLS-1$
    117         mNewDirText.setText(defaultPath);
    118         mNewDirText.addModifyListener(this);
    119 
    120         mNewDirButton = new Button(container, SWT.FLAT);
    121         mNewDirButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    122         mNewDirButton.setText("Browse...");
    123         mNewDirButton.addSelectionListener(this);
    124 
    125         Label spacing2 = new Label(container, SWT.NONE);
    126         spacing2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    127 
    128         mUseExistingRadio = new Button(container, SWT.RADIO);
    129         mUseExistingRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    130         mUseExistingRadio.setText("Use existing SDKs");
    131         mUseExistingRadio.addSelectionListener(this);
    132 
    133         new Label(container, SWT.NONE);
    134         Label installationLabel = new Label(container, SWT.NONE);
    135         installationLabel.setText("Existing Location:");
    136 
    137         mExistingDirText = new Text(container, SWT.BORDER);
    138         mExistingDirText.setEnabled(false);
    139         mExistingDirText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    140         mExistingDirText.addModifyListener(this);
    141 
    142         mExistingDirButton = new Button(container, SWT.FLAT);
    143         mExistingDirButton.setEnabled(false);
    144         mExistingDirButton.setText("Browse...");
    145         mExistingDirButton.addSelectionListener(this);
    146     }
    147 
    148     boolean isCreateNew() {
    149         return mInstallNewRadio.getSelection();
    150     }
    151 
    152     boolean isInstallLatest() {
    153         return mInstallLatestCheckbox.getSelection();
    154     }
    155 
    156     boolean isInstallCommon() {
    157         return mInstallCommonCheckbox.getSelection();
    158     }
    159 
    160     File getPath() {
    161         Text text = isCreateNew() ? mNewDirText : mExistingDirText;
    162         return new File(text.getText());
    163     }
    164 
    165     @Override
    166     public void widgetSelected(SelectionEvent e) {
    167         Object source = e.getSource();
    168 
    169         if (source == mExistingDirButton) {
    170             DirectoryDialog dialog = new DirectoryDialog(mExistingDirButton.getShell(), SWT.OPEN);
    171             String file = dialog.open();
    172             String path = mExistingDirText.getText().trim();
    173             if (path.length() > 0) {
    174                 // TODO: Shouldn't this be done before the open() call?
    175                 dialog.setFilterPath(path);
    176             }
    177             if (file != null) {
    178                 mExistingDirText.setText(file);
    179             }
    180         } else if (source == mNewDirButton) {
    181             DirectoryDialog dialog = new DirectoryDialog(mNewDirButton.getShell(), SWT.OPEN);
    182             String path = mNewDirText.getText().trim();
    183             if (path.length() > 0) {
    184                 dialog.setFilterPath(path);
    185             }
    186             String file = dialog.open();
    187             if (file != null) {
    188                 mNewDirText.setText(file);
    189             }
    190         } else if (source == mInstallNewRadio) {
    191             mExistingDirButton.setEnabled(false);
    192             mExistingDirText.setEnabled(false);
    193             mNewDirButton.setEnabled(true);
    194             mNewDirText.setEnabled(true);
    195         } else if (source == mUseExistingRadio) {
    196             mExistingDirButton.setEnabled(true);
    197             mExistingDirText.setEnabled(true);
    198             mNewDirButton.setEnabled(false);
    199             mNewDirText.setEnabled(false);
    200         }
    201 
    202         validatePage();
    203     }
    204 
    205     @Override
    206     public void widgetDefaultSelected(SelectionEvent e) {
    207     }
    208 
    209     @Override
    210     public void modifyText(ModifyEvent e) {
    211         validatePage();
    212     }
    213 
    214     private void validatePage() {
    215         String error = null;
    216         String warning = null;
    217 
    218         if (isCreateNew()) {
    219             // Make sure that the target installation directory is empty or doesn't exist
    220             // (and that it can be created)
    221             String path = mNewDirText.getText().trim();
    222             if (path.length() == 0) {
    223                 error = "Please enter a new directory to install the SDK into";
    224             } else {
    225                 File file = new File(path);
    226                 if (file.exists()) {
    227                     if (file.isDirectory()) {
    228                         if (!file.canWrite()) {
    229                             error = "Missing write permission in target directory";
    230                         }
    231                         File[] children = file.listFiles();
    232                         if (children != null && children.length > 0) {
    233                             warning = "The directory is not empty";
    234                         }
    235                     } else {
    236                         error = "The target must be a directory";
    237                     }
    238                 } else {
    239                     File parent = file.getParentFile();
    240                     if (parent == null || !parent.exists()) {
    241                         error = "The parent directory does not exist";
    242                     } else if (!parent.canWrite()) {
    243                         error = "No write permission in parent directory";
    244                     }
    245                 }
    246             }
    247 
    248             if (error == null && !mInstallLatestCheckbox.getSelection()
    249                     && !mInstallCommonCheckbox.getSelection()) {
    250                 error = "You must choose at least one Android version to install";
    251             }
    252         } else {
    253             // Make sure that the existing installation directory exists and is valid
    254             String path = mExistingDirText.getText().trim();
    255             if (path.length() == 0) {
    256                 error = "Please enter an existing SDK installation directory";
    257             } else {
    258                 File file = new File(path);
    259                 if (!file.exists()) {
    260                     error = "The chosen installation directory does not exist";
    261                 } else {
    262                     final AtomicReference<String> errorReference = new AtomicReference<String>();
    263                     final AtomicReference<String> warningReference = new AtomicReference<String>();
    264                     AdtPlugin.getDefault().checkSdkLocationAndId(path,
    265                             new AdtPlugin.CheckSdkErrorHandler() {
    266                         @Override
    267                         public boolean handleError(
    268                                 CheckSdkErrorHandler.Solution solution,
    269                                 String message) {
    270                             message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
    271                             errorReference.set(message);
    272                             return false;  // Apply/OK must be disabled
    273                         }
    274 
    275                         @Override
    276                         public boolean handleWarning(
    277                                 CheckSdkErrorHandler.Solution solution,
    278                                 String message) {
    279                             message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
    280                             warningReference.set(message);
    281                             return true;  // Apply/OK must be enabled
    282                         }
    283                     });
    284                     error = errorReference.get();
    285                     if (warning == null) {
    286                         warning = warningReference.get();
    287                     }
    288                 }
    289             }
    290         }
    291 
    292         setPageComplete(error == null);
    293         if (error != null) {
    294             setMessage(error, IMessageProvider.ERROR);
    295         } else if (warning != null) {
    296             setMessage(warning, IMessageProvider.WARNING);
    297         } else {
    298             setErrorMessage(null);
    299             setMessage(null);
    300         }
    301     }
    302 }
    303