diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java new file mode 100644 index 000000000..06c0300b7 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizardState.java @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2011 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.wizards.newproject; + +import com.android.SdkConstants; +import com.android.annotations.Nullable; +import com.android.ide.common.xml.ManifestData; +import com.android.ide.common.xml.ManifestData.Activity; +import com.android.ide.eclipse.adt.AdtConstants; +import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; +import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.internal.project.ProjectProperties; +import com.android.sdklib.internal.project.ProjectProperties.PropertyType; +import com.android.utils.Pair; +import com.android.xml.AndroidManifest; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.ui.IWorkingSet; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link NewProjectWizardState} holds the state used by the various pages + * in the {@link NewProjectWizard} and its variations, and it can also be used + * to pass project information to the {@link NewProjectCreator}. + */ +public class NewProjectWizardState { + /** The mode to run the wizard in: creating test, or sample, or plain project */ + public Mode mode; + + /** + * If true, the project should be created from an existing codebase (pointed + * to by the {@link #projectLocation} or in the case of sample projects, the + * {@link #chosenSample}. Otherwise, create a brand new project from scratch. + */ + public boolean useExisting; + + /** + * Whether new projects should be created into the default project location + * (e.g. in the Eclipse workspace) or not + */ + public boolean useDefaultLocation = true; + + /** The build target SDK */ + public IAndroidTarget target; + /** True if the user has manually modified the target */ + public boolean targetModifiedByUser; + + /** The location to store projects into */ + public File projectLocation = new File(Platform.getLocation().toOSString()); + /** True if the project location name has been manually edited by the user */ + public boolean projectLocationModifiedByUser; + + /** The name of the project */ + public String projectName = ""; //$NON-NLS-1$ + /** True if the project name has been manually edited by the user */ + public boolean projectNameModifiedByUser; + + /** The application name */ + public String applicationName; + /** True if the application name has been manually edited by the user */ + public boolean applicationNameModifiedByUser; + + /** The package path */ + public String packageName; + /** True if the package name has been manually edited by the user */ + public boolean packageNameModifiedByUser; + + /** True if a new activity should be created */ + public boolean createActivity; + + /** The name of the new activity to be created */ + public String activityName; + /** True if the activity name has been manually edited by the user */ + public boolean activityNameModifiedByUser; + + /** The minimum SDK version to use with the project (may be null or blank) */ + public String minSdk; + /** True if the minimum SDK version has been manually edited by the user */ + public boolean minSdkModifiedByUser; + /** + * A list of paths to each of the available samples for the current SDK. + * The pair is (String: sample display name => File: sample directory). + * Note we want a list, not a map since we might have duplicates. + * */ + public List<Pair<String, File>> samples = new ArrayList<Pair<String, File>>(); + /** Path to the currently chosen sample */ + public File chosenSample; + + /** The name of the source folder, relative to the project root */ + public String sourceFolder = SdkConstants.FD_SOURCES; + /** The set of chosen working sets to use when creating the project */ + public IWorkingSet[] workingSets = new IWorkingSet[0]; + + /** + * A reference to a different project that the current test project will be + * testing. + */ + public IProject testedProject; + /** + * If true, this test project should be testing itself, otherwise it will be + * testing the project pointed to by {@link #testedProject}. + */ + public boolean testingSelf; + + // NOTE: These apply only to creating paired projects; when isTest is true + // we're using + // the normal fields above + /** + * If true, create a test project along with this plain project which will + * be testing the plain project. (This flag only applies when creating + * normal projects.) + */ + public boolean createPairProject; + /** + * The application name of the test application (only applies when + * {@link #createPairProject} is true) + */ + public String testApplicationName; + /** + * True if the testing application name has been modified by the user (only + * applies when {@link #createPairProject} is true) + */ + public boolean testApplicationNameModified; + /** + * The package name of the test application (only applies when + * {@link #createPairProject} is true) + */ + public String testPackageName; + /** + * True if the testing package name has been modified by the user (only + * applies when {@link #createPairProject} is true) + */ + public boolean testPackageModified; + /** + * The project name of the test project (only applies when + * {@link #createPairProject} is true) + */ + public String testProjectName; + /** + * True if the testing project name has been modified by the user (only + * applies when {@link #createPairProject} is true) + */ + public boolean testProjectModified; + /** Package name of the tested app */ + public String testTargetPackageName; + + /** + * Copy project into workspace? This flag only applies when importing + * projects (creating projects from existing source) + */ + public boolean copyIntoWorkspace; + + /** + * List of projects to be imported. Null if not importing projects. + */ + @Nullable + public List<ImportedProject> importProjects; + + /** + * Creates a new {@link NewProjectWizardState} + * + * @param mode the mode to run the wizard in + */ + public NewProjectWizardState(Mode mode) { + this.mode = mode; + if (mode == Mode.SAMPLE) { + useExisting = true; + } else if (mode == Mode.TEST) { + createActivity = false; + } + } + + /** + * Extract information (package name, application name, minimum SDK etc) from + * the given Android project. + * + * @param path the path to the project to extract information from + */ + public void extractFromAndroidManifest(Path path) { + String osPath = path.append(SdkConstants.FN_ANDROID_MANIFEST_XML).toOSString(); + if (!(new File(osPath).exists())) { + return; + } + + ManifestData manifestData = AndroidManifestHelper.parseForData(osPath); + if (manifestData == null) { + return; + } + + String newPackageName = null; + Activity activity = null; + String newActivityName = null; + String minSdkVersion = null; + try { + newPackageName = manifestData.getPackage(); + minSdkVersion = manifestData.getMinSdkVersionString(); + + // try to get the first launcher activity. If none, just take the first activity. + activity = manifestData.getLauncherActivity(); + if (activity == null) { + Activity[] activities = manifestData.getActivities(); + if (activities != null && activities.length > 0) { + activity = activities[0]; + } + } + } catch (Exception e) { + // ignore exceptions + } + + if (newPackageName != null && newPackageName.length() > 0) { + packageName = newPackageName; + } + + if (activity != null) { + newActivityName = AndroidManifest.extractActivityName(activity.getName(), + newPackageName); + } + + if (newActivityName != null && newActivityName.length() > 0) { + activityName = newActivityName; + // we are "importing" an existing activity, not creating a new one + createActivity = false; + + // If project name and application names are empty, use the activity + // name as a default. If the activity name has dots, it's a part of a + // package specification and only the last identifier must be used. + if (newActivityName.indexOf('.') != -1) { + String[] ids = newActivityName.split(AdtConstants.RE_DOT); + newActivityName = ids[ids.length - 1]; + } + if (projectName == null || projectName.length() == 0 || + !projectNameModifiedByUser) { + projectName = newActivityName; + projectNameModifiedByUser = false; + } + if (applicationName == null || applicationName.length() == 0 || + !applicationNameModifiedByUser) { + applicationNameModifiedByUser = false; + applicationName = newActivityName; + } + } else { + activityName = ""; //$NON-NLS-1$ + + // There is no activity name to use to fill in the project and application + // name. However if there's a package name, we can use this as a base. + if (newPackageName != null && newPackageName.length() > 0) { + // Package name is a java identifier, so it's most suitable for + // an application name. + + if (applicationName == null || applicationName.length() == 0 || + !applicationNameModifiedByUser) { + applicationName = newPackageName; + } + + // For the project name, remove any dots + newPackageName = newPackageName.replace('.', '_'); + if (projectName == null || projectName.length() == 0 || + !projectNameModifiedByUser) { + projectName = newPackageName; + } + + } + } + + if (mode == Mode.ANY && useExisting) { + updateSdkTargetToMatchProject(path.toFile()); + } + + minSdk = minSdkVersion; + minSdkModifiedByUser = false; + } + + /** + * Try to find an SDK Target that matches the current MinSdkVersion. + * + * There can be multiple targets with the same sdk api version, so don't change + * it if it's already at the right version. Otherwise pick the first target + * that matches. + */ + public void updateSdkTargetToMatchMinSdkVersion() { + IAndroidTarget currentTarget = target; + if (currentTarget != null && currentTarget.getVersion().equals(minSdk)) { + return; + } + + Sdk sdk = Sdk.getCurrent(); + if (sdk != null) { + IAndroidTarget[] targets = sdk.getTargets(); + for (IAndroidTarget t : targets) { + if (t.getVersion().equals(minSdk)) { + target = t; + return; + } + } + } + } + + /** + * Updates the SDK to reflect the SDK required by the project at the given + * location + * + * @param location the location of the project + */ + public void updateSdkTargetToMatchProject(File location) { + // Select the target matching the manifest's sdk or build properties, if any + IAndroidTarget foundTarget = null; + // This is the target currently in the UI + IAndroidTarget currentTarget = target; + String projectPath = location.getPath(); + + // If there's a current target defined, we do not allow to change it when + // operating in the create-from-sample mode -- since the available sample list + // is tied to the current target, so changing it would invalidate the project we're + // trying to load in the first place. + if (!targetModifiedByUser) { + ProjectProperties p = ProjectProperties.load(projectPath, + PropertyType.PROJECT); + if (p != null) { + String v = p.getProperty(ProjectProperties.PROPERTY_TARGET); + IAndroidTarget desiredTarget = Sdk.getCurrent().getTargetFromHashString(v); + // We can change the current target if: + // - we found a new desired target + // - there is no current target + // - or the current target can't run the desired target + if (desiredTarget != null && + (currentTarget == null || !desiredTarget.canRunOn(currentTarget))) { + foundTarget = desiredTarget; + } + } + + Sdk sdk = Sdk.getCurrent(); + IAndroidTarget[] targets = null; + if (sdk != null) { + targets = sdk.getTargets(); + } + if (targets == null) { + targets = new IAndroidTarget[0]; + } + + if (foundTarget == null && minSdk != null) { + // Otherwise try to match the requested min-sdk-version if we find an + // exact match, regardless of the currently selected target. + for (IAndroidTarget existingTarget : targets) { + if (existingTarget != null && + existingTarget.getVersion().equals(minSdk)) { + foundTarget = existingTarget; + break; + } + } + } + + if (foundTarget == null) { + // Or last attempt, try to match a sample project location and use it + // if we find an exact match, regardless of the currently selected target. + for (IAndroidTarget existingTarget : targets) { + if (existingTarget != null && + projectPath.startsWith(existingTarget.getLocation())) { + foundTarget = existingTarget; + break; + } + } + } + } + + if (foundTarget != null) { + target = foundTarget; + } + } + + /** + * Type of project being offered/created by the wizard + */ + public enum Mode { + /** Create a sample project. Testing options are not presented. */ + SAMPLE, + + /** + * Create a test project, either testing itself or some other project. + * Note that even if in the {@link #ANY} mode, a test project can be + * created as a *paired* project with the main project, so this flag + * only means that we are creating *just* a test project + */ + TEST, + + /** + * Create an Android project, which can be a plain project, optionally + * with a paired test project, or a sample project (the first page + * contains toggles for choosing which + */ + ANY; + } +} |