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 import static org.eclipse.core.resources.IResource.DEPTH_INFINITE;
     19 
     20 import com.android.annotations.NonNull;
     21 import com.android.ide.eclipse.adt.AdtPlugin;
     22 import com.android.ide.eclipse.adt.internal.assetstudio.ConfigureAssetSetPage;
     23 import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState;
     24 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
     25 import com.google.common.collect.Lists;
     26 
     27 import org.eclipse.core.resources.IProject;
     28 import org.eclipse.core.runtime.CoreException;
     29 import org.eclipse.core.runtime.IProgressMonitor;
     30 import org.eclipse.core.runtime.NullProgressMonitor;
     31 import org.eclipse.jface.operation.IRunnableWithProgress;
     32 import org.eclipse.jface.resource.ImageDescriptor;
     33 import org.eclipse.jface.viewers.IStructuredSelection;
     34 import org.eclipse.jface.wizard.IWizardPage;
     35 import org.eclipse.jface.wizard.Wizard;
     36 import org.eclipse.jface.wizard.WizardPage;
     37 import org.eclipse.ltk.core.refactoring.Change;
     38 import org.eclipse.ltk.core.refactoring.CompositeChange;
     39 import org.eclipse.swt.widgets.Display;
     40 import org.eclipse.ui.INewWizard;
     41 import org.eclipse.ui.IWorkbench;
     42 import org.eclipse.ui.actions.WorkspaceModifyOperation;
     43 
     44 import java.lang.reflect.InvocationTargetException;
     45 import java.util.List;
     46 import java.util.concurrent.atomic.AtomicBoolean;
     47 
     48 import javax.swing.SwingUtilities;
     49 
     50 abstract class TemplateWizard extends Wizard implements INewWizard {
     51     private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
     52     protected IWorkbench mWorkbench;
     53     private UpdateToolsPage mUpdatePage;
     54     private InstallDependencyPage mDependencyPage;
     55     private TemplatePreviewPage mPreviewPage;
     56     protected ConfigureAssetSetPage mIconPage;
     57 
     58     protected TemplateWizard() {
     59     }
     60 
     61     /** Should this wizard add an icon page? */
     62     protected boolean shouldAddIconPage() {
     63         return false;
     64     }
     65 
     66     @Override
     67     public void init(IWorkbench workbench, IStructuredSelection selection) {
     68         mWorkbench = workbench;
     69 
     70         setHelpAvailable(false);
     71         ImageDescriptor desc = IconFactory.getInstance().getImageDescriptor(PROJECT_LOGO_LARGE);
     72         setDefaultPageImageDescriptor(desc);
     73 
     74         if (!UpdateToolsPage.isUpToDate()) {
     75             mUpdatePage = new UpdateToolsPage();
     76         }
     77 
     78         setNeedsProgressMonitor(true);
     79 
     80         // Trigger a check to see if the SDK needs to be reloaded (which will
     81         // invoke onSdkLoaded asynchronously as needed).
     82         AdtPlugin.getDefault().refreshSdk();
     83     }
     84 
     85     @Override
     86     public void addPages() {
     87         super.addPages();
     88         if (mUpdatePage != null) {
     89             addPage(mUpdatePage);
     90         }
     91     }
     92 
     93     @Override
     94     public IWizardPage getStartingPage() {
     95         if (mUpdatePage != null && mUpdatePage.isPageComplete()) {
     96             return getNextPage(mUpdatePage);
     97         }
     98 
     99         return super.getStartingPage();
    100     }
    101 
    102     protected WizardPage getPreviewPage(NewTemplateWizardState values) {
    103         if (mPreviewPage == null) {
    104             mPreviewPage = new TemplatePreviewPage(values);
    105             addPage(mPreviewPage);
    106         }
    107 
    108         return mPreviewPage;
    109     }
    110 
    111     protected WizardPage getIconPage(CreateAssetSetWizardState iconState) {
    112         if (mIconPage == null) {
    113             mIconPage = new ConfigureAssetSetPage(iconState);
    114             mIconPage.setTitle("Configure Icon");
    115             addPage(mIconPage);
    116         }
    117 
    118         return mIconPage;
    119     }
    120 
    121     protected WizardPage getDependencyPage(TemplateMetadata template, boolean create) {
    122         if (!create) {
    123             return mDependencyPage;
    124         }
    125 
    126         if (mDependencyPage == null) {
    127             mDependencyPage = new InstallDependencyPage();
    128             addPage(mDependencyPage);
    129         }
    130         mDependencyPage.setTemplate(template);
    131         return mDependencyPage;
    132     }
    133 
    134     /**
    135      * Returns the project where the template is being inserted
    136      *
    137      * @return the project to insert the template into
    138      */
    139     @NonNull
    140     protected abstract IProject getProject();
    141 
    142     /**
    143      * Returns the list of files to open, which might be empty. This method will
    144      * only be called <b>after</b> {@link #computeChanges()} has been called.
    145      *
    146      * @return a list of files to open
    147      */
    148     @NonNull
    149     protected abstract List<String> getFilesToOpen();
    150 
    151     /**
    152      * Returns the list of files to open, which might be empty. This method will
    153      * only be called <b>after</b> {@link #computeChanges()} has been called.
    154      *
    155      * @return a list of files to open
    156      */
    157     @NonNull
    158     protected abstract List<Runnable> getFinalizingActions();
    159 
    160     /**
    161      * Computes the changes to the {@link #getProject()} this template should
    162      * perform
    163      *
    164      * @return the changes to perform
    165      */
    166     protected abstract List<Change> computeChanges();
    167 
    168     protected boolean performFinish(IProgressMonitor monitor) throws InvocationTargetException {
    169         List<Change> changes = computeChanges();
    170         if (!changes.isEmpty()) {
    171             monitor.beginTask("Creating template...", changes.size());
    172             try {
    173                 CompositeChange composite = new CompositeChange("",
    174                         changes.toArray(new Change[changes.size()]));
    175                 composite.perform(monitor);
    176             } catch (CoreException e) {
    177                 AdtPlugin.log(e, null);
    178                 throw new InvocationTargetException(e);
    179             } finally {
    180                 monitor.done();
    181             }
    182         }
    183 
    184         // TBD: Is this necessary now that we're using IFile objects?
    185         try {
    186             getProject().refreshLocal(DEPTH_INFINITE, new NullProgressMonitor());
    187         } catch (CoreException e) {
    188             AdtPlugin.log(e, null);
    189         }
    190         return true;
    191     }
    192 
    193     @Override
    194     public boolean performFinish() {
    195         final AtomicBoolean success = new AtomicBoolean();
    196         try {
    197             getContainer().run(true, false, new IRunnableWithProgress() {
    198                 @Override
    199                 public void run(IProgressMonitor monitor) throws InvocationTargetException,
    200                 InterruptedException {
    201                     boolean ok = performFinish(monitor);
    202                     success.set(ok);
    203                 }
    204             });
    205 
    206         } catch (InvocationTargetException e) {
    207             AdtPlugin.log(e, null);
    208             return false;
    209         } catch (InterruptedException e) {
    210             AdtPlugin.log(e, null);
    211             return false;
    212         }
    213 
    214         if (success.get()) {
    215             // Open the primary file/files
    216             NewTemplateWizard.openFiles(getProject(), getFilesToOpen(), mWorkbench);
    217             return true;
    218         } else {
    219             return false;
    220         }
    221     }
    222 }
    223