Home | History | Annotate | Download | only in templates
      1 /*
      2  * Copyright (C) 2012 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.templates;
     17 
     18 
     19 import com.android.ide.eclipse.adt.AdtPlugin;
     20 import com.android.ide.eclipse.adt.internal.wizards.newproject.WorkingSetGroup;
     21 import com.android.ide.eclipse.adt.internal.wizards.newproject.WorkingSetHelper;
     22 
     23 import org.eclipse.core.runtime.IPath;
     24 import org.eclipse.core.runtime.IStatus;
     25 import org.eclipse.core.runtime.Platform;
     26 import org.eclipse.core.runtime.Status;
     27 import org.eclipse.jface.dialogs.IMessageProvider;
     28 import org.eclipse.jface.viewers.IStructuredSelection;
     29 import org.eclipse.jface.wizard.IWizardPage;
     30 import org.eclipse.jface.wizard.WizardPage;
     31 import org.eclipse.swt.SWT;
     32 import org.eclipse.swt.events.FocusEvent;
     33 import org.eclipse.swt.events.FocusListener;
     34 import org.eclipse.swt.events.ModifyEvent;
     35 import org.eclipse.swt.events.ModifyListener;
     36 import org.eclipse.swt.events.SelectionEvent;
     37 import org.eclipse.swt.events.SelectionListener;
     38 import org.eclipse.swt.layout.GridData;
     39 import org.eclipse.swt.layout.GridLayout;
     40 import org.eclipse.swt.widgets.Button;
     41 import org.eclipse.swt.widgets.Composite;
     42 import org.eclipse.swt.widgets.DirectoryDialog;
     43 import org.eclipse.swt.widgets.Label;
     44 import org.eclipse.swt.widgets.Shell;
     45 import org.eclipse.swt.widgets.Text;
     46 import org.eclipse.ui.IWorkbenchPart;
     47 import org.eclipse.ui.IWorkingSet;
     48 
     49 import java.io.File;
     50 
     51 /**
     52  * Second wizard page in the "New Project From Template" wizard
     53  */
     54 public class ProjectContentsPage extends WizardPage
     55         implements ModifyListener, SelectionListener, FocusListener {
     56 
     57     private final NewProjectWizardState mValues;
     58 
     59     private boolean mIgnore;
     60     private Button mCustomIconToggle;
     61     private Button mLibraryToggle;
     62 
     63     private Button mUseDefaultLocationToggle;
     64     private Label mLocationLabel;
     65     private Text mLocationText;
     66     private Button mChooseLocationButton;
     67     private static String sLastProjectLocation = System.getProperty("user.home"); //$NON-NLS-1$
     68     private Button mCreateActivityToggle;
     69     private WorkingSetGroup mWorkingSetGroup;
     70 
     71     ProjectContentsPage(NewProjectWizardState values) {
     72         super("newAndroidApp"); //$NON-NLS-1$
     73         mValues = values;
     74         setTitle("New Android Application");
     75         setDescription("Configure Project");
     76 
     77         mWorkingSetGroup = new WorkingSetGroup();
     78         setWorkingSets(new IWorkingSet[0]);
     79     }
     80 
     81     @Override
     82     public void createControl(Composite parent) {
     83         Composite container = new Composite(parent, SWT.NULL);
     84         setControl(container);
     85         GridLayout gl_container = new GridLayout(4, false);
     86         gl_container.horizontalSpacing = 10;
     87         container.setLayout(gl_container);
     88 
     89         mCustomIconToggle = new Button(container, SWT.CHECK);
     90         mCustomIconToggle.setSelection(true);
     91         mCustomIconToggle.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
     92         mCustomIconToggle.setText("Create custom launcher icon");
     93         mCustomIconToggle.setSelection(mValues.createIcon);
     94         mCustomIconToggle.addSelectionListener(this);
     95 
     96         mCreateActivityToggle = new Button(container, SWT.CHECK);
     97         mCreateActivityToggle.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false,
     98                 4, 1));
     99         mCreateActivityToggle.setText("Create activity");
    100         mCreateActivityToggle.setSelection(mValues.createActivity);
    101         mCreateActivityToggle.addSelectionListener(this);
    102 
    103         new Label(container, SWT.NONE).setLayoutData(
    104                 new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    105 
    106         mLibraryToggle = new Button(container, SWT.CHECK);
    107         mLibraryToggle.setSelection(true);
    108         mLibraryToggle.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    109         mLibraryToggle.setText("Mark this project as a library");
    110         mLibraryToggle.setSelection(mValues.isLibrary);
    111         mLibraryToggle.addSelectionListener(this);
    112 
    113         // Blank line
    114         new Label(container, SWT.NONE).setLayoutData(
    115                 new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    116 
    117         mUseDefaultLocationToggle = new Button(container, SWT.CHECK);
    118         mUseDefaultLocationToggle.setLayoutData(
    119                 new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    120         mUseDefaultLocationToggle.setText("Create Project in Workspace");
    121         mUseDefaultLocationToggle.addSelectionListener(this);
    122 
    123         mLocationLabel = new Label(container, SWT.NONE);
    124         mLocationLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    125         mLocationLabel.setText("Location:");
    126 
    127         mLocationText = new Text(container, SWT.BORDER);
    128         mLocationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
    129         mLocationText.addModifyListener(this);
    130 
    131         mChooseLocationButton = new Button(container, SWT.NONE);
    132         mChooseLocationButton.setText("Browse...");
    133         mChooseLocationButton.addSelectionListener(this);
    134         mChooseLocationButton.setEnabled(false);
    135         setUseCustomLocation(!mValues.useDefaultLocation);
    136 
    137         new Label(container, SWT.NONE).setLayoutData(
    138                 new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    139 
    140         Composite group = mWorkingSetGroup.createControl(container);
    141         group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 4, 1));
    142     }
    143 
    144     @Override
    145     public void setVisible(boolean visible) {
    146         super.setVisible(visible);
    147 
    148         if (visible) {
    149             try {
    150                 mIgnore = true;
    151                 mUseDefaultLocationToggle.setSelection(mValues.useDefaultLocation);
    152                 mLocationText.setText(mValues.projectLocation);
    153             } finally {
    154                 mIgnore = false;
    155             }
    156         }
    157 
    158         validatePage();
    159     }
    160 
    161     private void setUseCustomLocation(boolean en) {
    162         mValues.useDefaultLocation = !en;
    163         mUseDefaultLocationToggle.setSelection(!en);
    164         if (!en) {
    165             updateProjectLocation(mValues.projectName);
    166         }
    167 
    168         mLocationLabel.setEnabled(en);
    169         mLocationText.setEnabled(en);
    170         mChooseLocationButton.setEnabled(en);
    171     }
    172 
    173     void init(IStructuredSelection selection, IWorkbenchPart activePart) {
    174         setWorkingSets(WorkingSetHelper.getSelectedWorkingSet(selection, activePart));
    175     }
    176 
    177     /**
    178      * Returns the working sets to which the new project should be added.
    179      *
    180      * @return the selected working sets to which the new project should be added
    181      */
    182     private IWorkingSet[] getWorkingSets() {
    183         return mWorkingSetGroup.getSelectedWorkingSets();
    184     }
    185 
    186     /**
    187      * Sets the working sets to which the new project should be added.
    188      *
    189      * @param workingSets the initial selected working sets
    190      */
    191     private void setWorkingSets(IWorkingSet[] workingSets) {
    192         assert workingSets != null;
    193         mWorkingSetGroup.setWorkingSets(workingSets);
    194     }
    195 
    196     @Override
    197     public IWizardPage getNextPage() {
    198         // Sync working set data to the value object, since the WorkingSetGroup
    199         // doesn't let us add listeners to do this lazily
    200         mValues.workingSets = getWorkingSets();
    201 
    202         return super.getNextPage();
    203     }
    204 
    205     // ---- Implements ModifyListener ----
    206 
    207     @Override
    208     public void modifyText(ModifyEvent e) {
    209         if (mIgnore) {
    210             return;
    211         }
    212 
    213         Object source = e.getSource();
    214         if (source == mLocationText) {
    215             mValues.projectLocation = mLocationText.getText().trim();
    216         }
    217 
    218         validatePage();
    219     }
    220 
    221 
    222     /** If the project should be created in the workspace, then update the project location
    223      * based on the project name. */
    224     private void updateProjectLocation(String projectName) {
    225         if (projectName == null) {
    226             projectName = "";
    227         }
    228 
    229         boolean useDefaultLocation = mUseDefaultLocationToggle.getSelection();
    230 
    231         if (useDefaultLocation) {
    232             IPath workspace = Platform.getLocation();
    233             String projectLocation = workspace.append(projectName).toOSString();
    234             mLocationText.setText(projectLocation);
    235             mValues.projectLocation = projectLocation;
    236         }
    237     }
    238 
    239     // ---- Implements SelectionListener ----
    240 
    241     @Override
    242     public void widgetSelected(SelectionEvent e) {
    243         if (mIgnore) {
    244             return;
    245         }
    246 
    247         Object source = e.getSource();
    248         if (source == mCustomIconToggle) {
    249             mValues.createIcon = mCustomIconToggle.getSelection();
    250         } else if (source == mLibraryToggle) {
    251             mValues.isLibrary = mLibraryToggle.getSelection();
    252         } else if (source == mCreateActivityToggle) {
    253             mValues.createActivity = mCreateActivityToggle.getSelection();
    254         } else if (source == mUseDefaultLocationToggle) {
    255             boolean useDefault = mUseDefaultLocationToggle.getSelection();
    256             setUseCustomLocation(!useDefault);
    257         } else if (source == mChooseLocationButton) {
    258             String dir = promptUserForLocation(getShell());
    259             if (dir != null) {
    260                 mLocationText.setText(dir);
    261                 mValues.projectLocation = dir;
    262             }
    263         }
    264 
    265         validatePage();
    266     }
    267 
    268     private String promptUserForLocation(Shell shell) {
    269         DirectoryDialog dd = new DirectoryDialog(getShell());
    270         dd.setMessage("Select folder where project should be created");
    271 
    272         String curLocation = mLocationText.getText().trim();
    273         if (!curLocation.isEmpty()) {
    274             dd.setFilterPath(curLocation);
    275         } else if (sLastProjectLocation != null) {
    276             dd.setFilterPath(sLastProjectLocation);
    277         }
    278 
    279         String dir = dd.open();
    280         if (dir != null) {
    281             sLastProjectLocation = dir;
    282         }
    283 
    284         return dir;
    285     }
    286 
    287     @Override
    288     public void widgetDefaultSelected(SelectionEvent e) {
    289     }
    290 
    291     // ---- Implements FocusListener ----
    292 
    293     @Override
    294     public void focusGained(FocusEvent e) {
    295     }
    296 
    297     @Override
    298     public void focusLost(FocusEvent e) {
    299     }
    300 
    301     // Validation
    302 
    303     void validatePage() {
    304         IStatus status = validateProjectLocation();
    305 
    306         setPageComplete(status == null || status.getSeverity() != IStatus.ERROR);
    307         if (status != null) {
    308             setMessage(status.getMessage(),
    309                     status.getSeverity() == IStatus.ERROR
    310                         ? IMessageProvider.ERROR : IMessageProvider.WARNING);
    311         } else {
    312             setErrorMessage(null);
    313             setMessage(null);
    314         }
    315     }
    316 
    317     static IStatus validateLocationInWorkspace(NewProjectWizardState values) {
    318         if (values.useDefaultLocation) {
    319             return null;
    320         }
    321 
    322         // Validate location
    323         if (values.projectName != null) {
    324             File dest = Platform.getLocation().append(values.projectName).toFile();
    325             if (dest.exists()) {
    326                 return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, String.format(
    327                    "There is already a file or directory named \"%1$s\" in the selected location.",
    328                         values.projectName));
    329             }
    330         }
    331 
    332         return null;
    333     }
    334 
    335     private IStatus validateProjectLocation() {
    336         if (mValues.useDefaultLocation) {
    337             return validateLocationInWorkspace(mValues);
    338         }
    339 
    340         String location = mLocationText.getText();
    341         if (location.trim().isEmpty()) {
    342             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    343                     "Provide a valid file system location where the project should be created.");
    344         }
    345 
    346         File f = new File(location);
    347         if (f.exists()) {
    348             if (!f.isDirectory()) {
    349                 return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    350                         String.format("'%s' is not a valid folder.", location));
    351             }
    352 
    353             File[] children = f.listFiles();
    354             if (children != null && children.length > 0) {
    355                 return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    356                         String.format("Folder '%s' is not empty.", location));
    357             }
    358         }
    359 
    360         // if the folder doesn't exist, then make sure that the parent
    361         // exists and is a writable folder
    362         File parent = f.getParentFile();
    363         if (!parent.exists()) {
    364             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    365                     String.format("Folder '%s' does not exist.", parent.getName()));
    366         }
    367 
    368         if (!parent.isDirectory()) {
    369             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    370                     String.format("'%s' is not a folder.", parent.getName()));
    371         }
    372 
    373         if (!parent.canWrite()) {
    374             return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
    375                     String.format("'%s' is not writeable.", parent.getName()));
    376         }
    377 
    378         return null;
    379     }
    380 }
    381