| /* |
| * Copyright 2000-2012 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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 org.jetbrains.android.facet; |
| |
| import com.android.SdkConstants; |
| import com.intellij.facet.ui.FacetEditorContext; |
| import com.intellij.facet.ui.FacetEditorTab; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.fileChooser.FileChooser; |
| import com.intellij.openapi.fileChooser.FileChooserDescriptor; |
| import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.options.ConfigurationException; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.ModuleRootManager; |
| import com.intellij.openapi.ui.ComboBox; |
| import com.intellij.openapi.ui.TextFieldWithBrowseButton; |
| import com.intellij.openapi.util.Condition; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VfsUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.ui.CheckBoxList; |
| import com.intellij.ui.ComboboxWithBrowseButton; |
| import com.intellij.ui.ListCellRendererWrapper; |
| import com.intellij.ui.RawCommandLineEditor; |
| import com.intellij.ui.components.JBCheckBox; |
| import com.intellij.ui.components.JBLabel; |
| import com.intellij.ui.components.JBTabbedPane; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.Function; |
| import com.intellij.util.PathUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.android.compiler.AndroidAutogeneratorMode; |
| import org.jetbrains.android.compiler.AndroidCompileUtil; |
| import org.jetbrains.android.compiler.artifact.ProGuardConfigFilesPanel; |
| import org.jetbrains.android.maven.AndroidMavenProvider; |
| import org.jetbrains.android.maven.AndroidMavenUtil; |
| import org.jetbrains.android.util.AndroidBundle; |
| import org.jetbrains.android.util.AndroidUtils; |
| import org.jetbrains.annotations.Nls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.jetbrains.jps.android.model.impl.AndroidImportableProperty; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.io.File; |
| import java.util.*; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class AndroidFacetEditorTab extends FacetEditorTab { |
| private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.facet.AndroidFacetEditorTab"); |
| |
| private final AndroidFacetConfiguration myConfiguration; |
| private final FacetEditorContext myContext; |
| private JPanel myContentPanel; |
| private TextFieldWithBrowseButton myRGenPathField; |
| private TextFieldWithBrowseButton myAidlGenPathField; |
| private JButton myResetPathsButton; |
| private TextFieldWithBrowseButton myResFolderField; |
| private TextFieldWithBrowseButton myAssetsFolderField; |
| private TextFieldWithBrowseButton myNativeLibsFolder; |
| private TextFieldWithBrowseButton myManifestFileField; |
| private JRadioButton myUseAptResDirectoryFromPathRadio; |
| private JRadioButton myUseCustomSourceDirectoryRadio; |
| private TextFieldWithBrowseButton myCustomAptSourceDirField; |
| private JCheckBox myIsLibraryProjectCheckbox; |
| private JPanel myAaptCompilerPanel; |
| private ComboboxWithBrowseButton myApkPathCombo; |
| private JLabel myApkPathLabel; |
| private JRadioButton myRunProcessResourcesRadio; |
| private JRadioButton myCompileResourcesByIdeRadio; |
| private JLabel myManifestFileLabel; |
| private JLabel myResFolderLabel; |
| private JLabel myAssetsFolderLabel; |
| private JLabel myNativeLibsFolderLabel; |
| private JLabel myAidlGenPathLabel; |
| private JLabel myRGenPathLabel; |
| private TextFieldWithBrowseButton myCustomDebugKeystoreField; |
| private JBLabel myCustomKeystoreLabel; |
| private JCheckBox myIncludeTestCodeAndCheckBox; |
| private JBCheckBox myRunProguardCheckBox; |
| private JBCheckBox myIncludeAssetsFromLibraries; |
| private JBCheckBox myUseCustomManifestPackage; |
| private JTextField myCustomManifestPackageField; |
| private ComboBox myUpdateProjectPropertiesCombo; |
| private CheckBoxList<AndroidImportableProperty> myImportedOptionsList; |
| private JBTabbedPane myTabbedPane; |
| private JBCheckBox myEnableManifestMerging; |
| private JBCheckBox myPreDexEnabledCheckBox; |
| private ProGuardConfigFilesPanel myProGuardConfigFilesPanel; |
| private JBCheckBox myEnableSourcesAutogenerationCheckBox; |
| private JPanel myAptAutogenerationOptionsPanel; |
| private JPanel myAidlAutogenerationOptionsPanel; |
| private RawCommandLineEditor myAdditionalPackagingCommandLineParametersField; |
| private TextFieldWithBrowseButton myProguardLogsDirectoryField; |
| private JBLabel myProGuardLogsDirectoryLabel; |
| |
| private static final String MAVEN_TAB_TITLE = "Maven"; |
| private final Component myMavenTabComponent; |
| |
| public AndroidFacetEditorTab(FacetEditorContext context, AndroidFacetConfiguration androidFacetConfiguration) { |
| final Project project = context.getProject(); |
| myConfiguration = androidFacetConfiguration; |
| myContext = context; |
| |
| myManifestFileLabel.setLabelFor(myManifestFileField); |
| myResFolderLabel.setLabelFor(myResFolderField); |
| myAssetsFolderLabel.setLabelFor(myAssetsFolderField); |
| myNativeLibsFolderLabel.setLabelFor(myNativeLibsFolder); |
| myAidlGenPathLabel.setLabelFor(myAidlGenPathField); |
| myRGenPathLabel.setLabelFor(myRGenPathField); |
| myCustomKeystoreLabel.setLabelFor(myCustomDebugKeystoreField); |
| |
| final AndroidFacet facet = (AndroidFacet)myContext.getFacet(); |
| |
| myRGenPathField.getButton() |
| .addActionListener(new MyGenSourceFieldListener(myRGenPathField, AndroidRootUtil.getAptGenSourceRootPath(facet))); |
| myAidlGenPathField.getButton() |
| .addActionListener(new MyGenSourceFieldListener(myAidlGenPathField, AndroidRootUtil.getAidlGenSourceRootPath(facet))); |
| |
| Module module = myContext.getModule(); |
| |
| myManifestFileField.getButton().addActionListener( |
| new MyFolderFieldListener(myManifestFileField, AndroidRootUtil.getManifestFile(facet), true, new MyManifestFilter())); |
| |
| myResFolderField.getButton().addActionListener(new MyFolderFieldListener(myResFolderField, |
| AndroidRootUtil.getResourceDir(facet), false, null)); |
| |
| myAssetsFolderField.getButton().addActionListener(new MyFolderFieldListener(myAssetsFolderField, |
| AndroidRootUtil.getAssetsDir(facet), false, null)); |
| |
| myNativeLibsFolder.getButton().addActionListener(new MyFolderFieldListener(myNativeLibsFolder, |
| AndroidRootUtil.getLibsDir(facet), false, null)); |
| |
| myCustomAptSourceDirField.getButton().addActionListener(new MyFolderFieldListener(myCustomAptSourceDirField, getCustomResourceDirForApt(facet), false, null)); |
| |
| myRunProguardCheckBox.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| myProGuardConfigFilesPanel.setEnabled(myRunProguardCheckBox.isSelected()); |
| } |
| }); |
| |
| myCustomDebugKeystoreField.getButton().addActionListener(new MyFolderFieldListener(myCustomDebugKeystoreField, null, true, null)); |
| |
| myResetPathsButton.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| AndroidFacetConfiguration configuration = new AndroidFacetConfiguration(); |
| configuration.setFacet((AndroidFacet)myContext.getFacet()); |
| Module module = myContext.getModule(); |
| VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); |
| if (contentRoots.length == 1) { |
| configuration.init(module, contentRoots[0]); |
| } |
| if (AndroidMavenUtil.isMavenizedModule(module)) { |
| AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider(); |
| if (mavenProvider != null) { |
| mavenProvider.setPathsToDefault(module, configuration); |
| } |
| } |
| resetOptions(configuration); |
| } |
| }); |
| |
| myEnableSourcesAutogenerationCheckBox.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| updateAutogenerationPanels(); |
| } |
| }); |
| ActionListener listener = new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| myCustomAptSourceDirField.setEnabled(myUseCustomSourceDirectoryRadio.isSelected()); |
| } |
| }; |
| myUseCustomSourceDirectoryRadio.addActionListener(listener); |
| myUseAptResDirectoryFromPathRadio.addActionListener(listener); |
| |
| myIsLibraryProjectCheckbox.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| updateLibAndAppSpecificFields(); |
| } |
| }); |
| |
| listener = new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| updateAptPanel(); |
| } |
| }; |
| myRunProcessResourcesRadio.addActionListener(listener); |
| myCompileResourcesByIdeRadio.addActionListener(listener); |
| |
| myApkPathLabel.setLabelFor(myApkPathCombo); |
| |
| final JComboBox apkPathComboBoxComponent = myApkPathCombo.getComboBox(); |
| apkPathComboBoxComponent.setEditable(true); |
| apkPathComboBoxComponent.setModel(new DefaultComboBoxModel(getDefaultApks(module))); |
| apkPathComboBoxComponent.setMinimumSize(new Dimension(10, apkPathComboBoxComponent.getMinimumSize().height)); |
| apkPathComboBoxComponent.setPreferredSize(new Dimension(10, apkPathComboBoxComponent.getPreferredSize().height)); |
| |
| myApkPathCombo.addBrowseFolderListener(project, new FileChooserDescriptor(true, false, false, false, false, false) { |
| @Override |
| public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { |
| if (!super.isFileVisible(file, showHiddenFiles)) { |
| return false; |
| } |
| return file.isDirectory() || "apk".equals(file.getExtension()); |
| } |
| }); |
| |
| myUseCustomManifestPackage.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| myCustomManifestPackageField.setEnabled(myUseCustomManifestPackage.isSelected()); |
| } |
| }); |
| |
| myUpdateProjectPropertiesCombo.setModel(new DefaultComboBoxModel(new Object[]{"", Boolean.TRUE.toString(), Boolean.FALSE.toString()})); |
| myUpdateProjectPropertiesCombo.setRenderer(new ListCellRendererWrapper<String>() { |
| @Override |
| public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) { |
| if (value != null && value.isEmpty()) { |
| setText("Ask"); |
| } |
| else if (Boolean.parseBoolean(value)) { |
| setText("Yes"); |
| } |
| else { |
| setText("No"); |
| } |
| } |
| }); |
| buildImportedOptionsList(); |
| |
| final int mavenTabIndex = myTabbedPane.indexOfTab(MAVEN_TAB_TITLE); |
| assert mavenTabIndex >= 0; |
| myMavenTabComponent = myTabbedPane.getComponentAt(mavenTabIndex); |
| |
| myProguardLogsDirectoryField.getButton().addActionListener(new MyFolderFieldListener(myProguardLogsDirectoryField, null, false, null)); |
| } |
| |
| @Nullable |
| public static VirtualFile getCustomResourceDirForApt(@NotNull AndroidFacet facet) { |
| return AndroidRootUtil.getFileByRelativeModulePath(facet.getModule(), facet.getProperties().CUSTOM_APK_RESOURCE_FOLDER, false); |
| } |
| |
| private void updateLibAndAppSpecificFields() { |
| boolean lib = myIsLibraryProjectCheckbox.isSelected(); |
| myAssetsFolderField.setEnabled(!lib); |
| myEnableManifestMerging.setEnabled(!lib); |
| myIncludeAssetsFromLibraries.setEnabled(!lib); |
| myUseCustomManifestPackage.setEnabled(!lib); |
| myCustomManifestPackageField.setEnabled(!lib && myUseCustomManifestPackage.isSelected()); |
| myAdditionalPackagingCommandLineParametersField.setEnabled(!lib); |
| myRunProguardCheckBox.setEnabled(!lib); |
| myProGuardConfigFilesPanel.setEnabled(!lib && myRunProguardCheckBox.isSelected()); |
| myApkPathLabel.setEnabled(!lib); |
| myApkPathCombo.setEnabled(!lib); |
| myCustomKeystoreLabel.setEnabled(!lib); |
| myCustomDebugKeystoreField.setEnabled(!lib); |
| myPreDexEnabledCheckBox.setEnabled(!lib); |
| myProGuardLogsDirectoryLabel.setEnabled(!lib); |
| myProguardLogsDirectoryField.setEnabled(!lib); |
| } |
| |
| private void updateAutogenerationPanels() { |
| UIUtil.setEnabled(myAidlAutogenerationOptionsPanel, myEnableSourcesAutogenerationCheckBox.isSelected(), true); |
| updateAptPanel(); |
| } |
| |
| private void buildImportedOptionsList() { |
| myImportedOptionsList.setItems(Arrays.asList(AndroidImportableProperty.values()), new Function<AndroidImportableProperty, String>() { |
| @Override |
| public String fun(AndroidImportableProperty property) { |
| return property.getDisplayName(); |
| } |
| }); |
| } |
| |
| private void updateAptPanel() { |
| if (!myEnableSourcesAutogenerationCheckBox.isSelected()) { |
| UIUtil.setEnabled(myAptAutogenerationOptionsPanel, false, true); |
| } |
| else { |
| UIUtil.setEnabled(myAptAutogenerationOptionsPanel, true, true); |
| boolean enabled = !myRunProcessResourcesRadio.isVisible() || !myRunProcessResourcesRadio.isSelected(); |
| UIUtil.setEnabled(myAaptCompilerPanel, enabled, true); |
| } |
| } |
| |
| private static String[] getDefaultApks(@NotNull Module module) { |
| List<String> result = new ArrayList<String>(); |
| String path = AndroidCompileUtil.getOutputPackage(module); |
| if (path != null) { |
| result.add(path); |
| } |
| AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider(); |
| if (mavenProvider != null && mavenProvider.isMavenizedModule(module)) { |
| String buildDirectory = mavenProvider.getBuildDirectory(module); |
| if (buildDirectory != null) { |
| result.add(FileUtil.toSystemDependentName(buildDirectory + '/' + AndroidCompileUtil.getApkName(module))); |
| } |
| } |
| return ArrayUtil.toStringArray(result); |
| } |
| |
| @Override |
| @Nls |
| public String getDisplayName() { |
| return "Android SDK Settings"; |
| } |
| |
| @NotNull |
| @Override |
| public JComponent createComponent() { |
| return myContentPanel; |
| } |
| |
| @Override |
| public boolean isModified() { |
| //if (myAddAndroidLibrary.isSelected() != myConfiguration.ADD_ANDROID_LIBRARY) return true; |
| if (myIsLibraryProjectCheckbox.isSelected() != myConfiguration.getState().LIBRARY_PROJECT) return true; |
| |
| if (checkRelativePath(myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_APT, myRGenPathField.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_AIDL, myAidlGenPathField.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().MANIFEST_FILE_RELATIVE_PATH, myManifestFileField.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().RES_FOLDER_RELATIVE_PATH, myResFolderField.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().ASSETS_FOLDER_RELATIVE_PATH, myAssetsFolderField.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().LIBS_FOLDER_RELATIVE_PATH, myNativeLibsFolder.getText())) { |
| return true; |
| } |
| |
| if (checkRelativePath(myConfiguration.getState().APK_PATH, (String)myApkPathCombo.getComboBox().getEditor().getItem())) { |
| return true; |
| } |
| |
| if (myUseCustomSourceDirectoryRadio.isSelected() != myConfiguration.getState().USE_CUSTOM_APK_RESOURCE_FOLDER) { |
| return true; |
| } |
| if (checkRelativePath(myConfiguration.getState().CUSTOM_APK_RESOURCE_FOLDER, myCustomAptSourceDirField.getText())) { |
| return true; |
| } |
| |
| if (myRunProcessResourcesRadio.isSelected() != myConfiguration.getState().RUN_PROCESS_RESOURCES_MAVEN_TASK) { |
| return true; |
| } |
| if (!myConfiguration.getState().CUSTOM_DEBUG_KEYSTORE_PATH.equals(getSelectedCustomKeystorePath())) { |
| return true; |
| } |
| if (myConfiguration.getState().ENABLE_MANIFEST_MERGING != myEnableManifestMerging.isSelected()) { |
| return true; |
| } |
| if (myConfiguration.getState().ENABLE_PRE_DEXING != myPreDexEnabledCheckBox.isSelected()) { |
| return true; |
| } |
| if (myConfiguration.getState().PACK_TEST_CODE != myIncludeTestCodeAndCheckBox.isSelected()) { |
| return true; |
| } |
| if (myConfiguration.getState().ENABLE_SOURCES_AUTOGENERATION != myEnableSourcesAutogenerationCheckBox.isSelected()) { |
| return true; |
| } |
| if (myConfiguration.isIncludeAssetsFromLibraries() != myIncludeAssetsFromLibraries.isSelected()) { |
| return true; |
| } |
| if (myConfiguration.getState().RUN_PROGUARD != myRunProguardCheckBox.isSelected()) { |
| return true; |
| } |
| if (!myProGuardConfigFilesPanel.getUrls().equals(myConfiguration.getState().myProGuardCfgFiles)) { |
| return true; |
| } |
| if (myConfiguration.getState().USE_CUSTOM_MANIFEST_PACKAGE != myUseCustomManifestPackage.isSelected()) { |
| return true; |
| } |
| if (!myCustomManifestPackageField.getText().trim().equals(myConfiguration.getState().CUSTOM_MANIFEST_PACKAGE)) { |
| return true; |
| } |
| if (!myAdditionalPackagingCommandLineParametersField.getText().trim().equals( |
| myConfiguration.getState().ADDITIONAL_PACKAGING_COMMAND_LINE_PARAMETERS)) { |
| return true; |
| } |
| if (!myUpdateProjectPropertiesCombo.getSelectedItem().equals(myConfiguration.getState().UPDATE_PROPERTY_FILES)) { |
| return true; |
| } |
| if (checkRelativePath(myConfiguration.getState().PROGUARD_LOGS_FOLDER_RELATIVE_PATH, myProguardLogsDirectoryField.getText())) { |
| return true; |
| } |
| if (AndroidMavenUtil.isMavenizedModule(myContext.getModule())) { |
| final Set<AndroidImportableProperty> newNotImportedProperties = EnumSet.noneOf(AndroidImportableProperty.class); |
| |
| for (int i = 0; i < myImportedOptionsList.getItemsCount(); i++) { |
| final AndroidImportableProperty property = (AndroidImportableProperty)myImportedOptionsList.getItemAt(i); |
| |
| if (!myImportedOptionsList.isItemSelected(i)) { |
| newNotImportedProperties.add(property); |
| } |
| } |
| |
| if (!myConfiguration.getState().myNotImportedProperties.equals(newNotImportedProperties)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @NotNull |
| private String getSelectedCustomKeystorePath() { |
| final String path = myCustomDebugKeystoreField.getText().trim(); |
| return path.length() > 0 ? VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(path)) : ""; |
| } |
| |
| private boolean checkRelativePath(String relativePathFromConfig, String absPathFromTextField) { |
| String pathFromConfig = relativePathFromConfig; |
| if (pathFromConfig != null && pathFromConfig.length() > 0) { |
| pathFromConfig = toAbsolutePath(pathFromConfig); |
| } |
| String pathFromTextField = absPathFromTextField.trim(); |
| return !FileUtil.pathsEqual(pathFromConfig, pathFromTextField); |
| } |
| |
| @Nullable |
| private String toRelativePath(String absPath) { |
| absPath = FileUtil.toSystemIndependentName(absPath); |
| String moduleDirPath = AndroidRootUtil.getModuleDirPath(myContext.getModule()); |
| if (moduleDirPath != null) { |
| moduleDirPath = FileUtil.toSystemIndependentName(moduleDirPath); |
| return FileUtil.getRelativePath(moduleDirPath, absPath, '/'); |
| } |
| return null; |
| } |
| |
| @Override |
| public String getHelpTopic() { |
| return "reference.settings.project.modules.android.facet"; |
| } |
| |
| @Override |
| public void apply() throws ConfigurationException { |
| if (!isModified()) return; |
| String absGenPathR = myRGenPathField.getText().trim(); |
| String absGenPathAidl = myAidlGenPathField.getText().trim(); |
| |
| boolean runApt = false; |
| boolean runIdl = false; |
| |
| if (absGenPathR == null || absGenPathR.length() == 0 || absGenPathAidl == null || absGenPathAidl.length() == 0) { |
| throw new ConfigurationException("Please specify source root for autogenerated files"); |
| } |
| else { |
| String relativeGenPathR = getAndCheckRelativePath(absGenPathR, false); |
| String newAptDestDir = '/' + relativeGenPathR; |
| if (!newAptDestDir.equals(myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_APT)) { |
| runApt = true; |
| } |
| myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_APT = newAptDestDir; |
| |
| String relativeGenPathAidl = getAndCheckRelativePath(absGenPathAidl, false); |
| String newIdlDestDir = '/' + relativeGenPathAidl; |
| if (!newIdlDestDir.equals(myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_AIDL)) { |
| runIdl = true; |
| } |
| myConfiguration.getState().GEN_FOLDER_RELATIVE_PATH_AIDL = newIdlDestDir; |
| } |
| |
| String absManifestPath = myManifestFileField.getText().trim(); |
| if (absManifestPath.length() == 0) { |
| throw new ConfigurationException("Manifest file not specified"); |
| } |
| String manifestRelPath = getAndCheckRelativePath(absManifestPath, true); |
| if (!SdkConstants.FN_ANDROID_MANIFEST_XML.equals(AndroidUtils.getSimpleNameByRelativePath(manifestRelPath))) { |
| throw new ConfigurationException("Manifest file must have name AndroidManifest.xml"); |
| } |
| myConfiguration.getState().MANIFEST_FILE_RELATIVE_PATH = '/' + manifestRelPath; |
| |
| String absResPath = myResFolderField.getText().trim(); |
| if (absResPath.length() == 0) { |
| throw new ConfigurationException("Resources folder not specified"); |
| } |
| myConfiguration.getState().RES_FOLDER_RELATIVE_PATH = '/' + getAndCheckRelativePath(absResPath, false); |
| |
| String absAssetsPath = myAssetsFolderField.getText().trim(); |
| myConfiguration.getState().ASSETS_FOLDER_RELATIVE_PATH = absAssetsPath.length() > 0 ? '/' + getAndCheckRelativePath(absAssetsPath, false) : ""; |
| |
| String absApkPath = (String)myApkPathCombo.getComboBox().getEditor().getItem(); |
| if (absApkPath.length() == 0) { |
| myConfiguration.getState().APK_PATH = ""; |
| } |
| else { |
| myConfiguration.getState().APK_PATH = '/' + getAndCheckRelativePath(absApkPath, false); |
| } |
| |
| String absLibsPath = myNativeLibsFolder.getText().trim(); |
| myConfiguration.getState().LIBS_FOLDER_RELATIVE_PATH = absLibsPath.length() > 0 ? '/' + getAndCheckRelativePath(absLibsPath, false) : ""; |
| |
| myConfiguration.getState().CUSTOM_DEBUG_KEYSTORE_PATH = getSelectedCustomKeystorePath(); |
| |
| myConfiguration.getState().LIBRARY_PROJECT = myIsLibraryProjectCheckbox.isSelected(); |
| |
| myConfiguration.getState().RUN_PROCESS_RESOURCES_MAVEN_TASK = myRunProcessResourcesRadio.isSelected(); |
| |
| myConfiguration.getState().ENABLE_MANIFEST_MERGING = myEnableManifestMerging.isSelected(); |
| |
| myConfiguration.getState().ENABLE_PRE_DEXING = myPreDexEnabledCheckBox.isSelected(); |
| |
| myConfiguration.getState().PACK_TEST_CODE = myIncludeTestCodeAndCheckBox.isSelected(); |
| |
| myConfiguration.getState().ENABLE_SOURCES_AUTOGENERATION = myEnableSourcesAutogenerationCheckBox.isSelected(); |
| |
| myConfiguration.setIncludeAssetsFromLibraries(myIncludeAssetsFromLibraries.isSelected()); |
| |
| if (AndroidMavenUtil.isMavenizedModule(myContext.getModule())) { |
| final Set<AndroidImportableProperty> notImportedProperties = myConfiguration.getState().myNotImportedProperties; |
| notImportedProperties.clear(); |
| |
| for (int i = 0; i < myImportedOptionsList.getItemsCount(); i++) { |
| final AndroidImportableProperty property = (AndroidImportableProperty)myImportedOptionsList.getItemAt(i); |
| |
| if (!myImportedOptionsList.isItemSelected(i)) { |
| notImportedProperties.add(property); |
| } |
| } |
| } |
| myConfiguration.getState().RUN_PROGUARD = myRunProguardCheckBox.isSelected(); |
| myConfiguration.getState().myProGuardCfgFiles = myProGuardConfigFilesPanel.getUrls(); |
| |
| boolean useCustomAptSrc = myUseCustomSourceDirectoryRadio.isSelected(); |
| |
| myConfiguration.getState().USE_CUSTOM_APK_RESOURCE_FOLDER = useCustomAptSrc; |
| |
| myConfiguration.getState().USE_CUSTOM_MANIFEST_PACKAGE = myUseCustomManifestPackage.isSelected(); |
| myConfiguration.getState().CUSTOM_MANIFEST_PACKAGE = myCustomManifestPackageField.getText().trim(); |
| myConfiguration.getState().ADDITIONAL_PACKAGING_COMMAND_LINE_PARAMETERS = myAdditionalPackagingCommandLineParametersField.getText().trim(); |
| |
| String absAptSourcePath = myCustomAptSourceDirField.getText().trim(); |
| if (useCustomAptSrc) { |
| if (absAptSourcePath.length() == 0) { |
| throw new ConfigurationException("Resources folder not specified"); |
| } |
| myConfiguration.getState().CUSTOM_APK_RESOURCE_FOLDER = '/' + getAndCheckRelativePath(absAptSourcePath, false); |
| } |
| else { |
| String relPath = toRelativePath(absAptSourcePath); |
| myConfiguration.getState().CUSTOM_APK_RESOURCE_FOLDER = relPath != null ? '/' + relPath : ""; |
| } |
| myConfiguration.getState().UPDATE_PROPERTY_FILES = (String)myUpdateProjectPropertiesCombo.getSelectedItem(); |
| |
| String absProguardLogsPath = myProguardLogsDirectoryField.getText().trim(); |
| myConfiguration.getState().PROGUARD_LOGS_FOLDER_RELATIVE_PATH = |
| absProguardLogsPath.length() > 0 ? '/' + getAndCheckRelativePath(absProguardLogsPath, false) : ""; |
| |
| if (runApt || runIdl) { |
| final Module module = myContext.getModule(); |
| |
| if (runApt) { |
| AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AAPT); |
| } |
| if (runIdl) { |
| AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AIDL); |
| } |
| } |
| } |
| |
| private String getAndCheckRelativePath(String absPath, boolean checkExists) throws ConfigurationException { |
| if (absPath.indexOf('/') < 0 && absPath.indexOf(File.separatorChar) < 0) { |
| throw new ConfigurationException(AndroidBundle.message("file.must.be.under.module.error", FileUtil.toSystemDependentName(absPath))); |
| } |
| String relativeGenPathR = toRelativePath(absPath); |
| if (relativeGenPathR == null || relativeGenPathR.length() == 0) { |
| throw new ConfigurationException(AndroidBundle.message("file.must.be.under.module.error", FileUtil.toSystemDependentName(absPath))); |
| } |
| if (checkExists && LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(absPath)) == null) { |
| throw new ConfigurationException(AndroidBundle.message("android.file.not.exist.error", FileUtil.toSystemDependentName(absPath))); |
| } |
| return relativeGenPathR; |
| } |
| |
| @Override |
| public void reset() { |
| myIsLibraryProjectCheckbox.setSelected(myConfiguration.getState().LIBRARY_PROJECT); |
| resetOptions(myConfiguration); |
| } |
| |
| private void resetOptions(AndroidFacetConfiguration configuration) { |
| String aptGenPath = configuration.getState().GEN_FOLDER_RELATIVE_PATH_APT; |
| String aptAbspath = aptGenPath.length() > 0 ? toAbsolutePath(aptGenPath) : ""; |
| myRGenPathField.setText(aptAbspath != null ? aptAbspath : ""); |
| |
| String aidlGenPath = configuration.getState().GEN_FOLDER_RELATIVE_PATH_AIDL; |
| String aidlAbsPath = aidlGenPath.length() > 0 ? toAbsolutePath(aidlGenPath) : ""; |
| myAidlGenPathField.setText(aidlAbsPath != null ? aidlAbsPath : ""); |
| |
| String manifestPath = configuration.getState().MANIFEST_FILE_RELATIVE_PATH; |
| String manifestAbsPath = manifestPath.length() > 0 ? toAbsolutePath(manifestPath) : ""; |
| myManifestFileField.setText(manifestAbsPath != null ? manifestAbsPath : ""); |
| |
| String resPath = configuration.getState().RES_FOLDER_RELATIVE_PATH; |
| String resAbsPath = resPath.length() > 0 ? toAbsolutePath(resPath) : ""; |
| myResFolderField.setText(resAbsPath != null ? resAbsPath : ""); |
| |
| String assetsPath = configuration.getState().ASSETS_FOLDER_RELATIVE_PATH; |
| String assetsAbsPath = assetsPath.length() > 0 ? toAbsolutePath(assetsPath) : ""; |
| myAssetsFolderField.setText(assetsAbsPath != null ? assetsAbsPath : ""); |
| |
| String libsPath = configuration.getState().LIBS_FOLDER_RELATIVE_PATH; |
| String libsAbsPath = libsPath.length() > 0 ? toAbsolutePath(libsPath) : ""; |
| myNativeLibsFolder.setText(libsAbsPath != null ? libsAbsPath : ""); |
| |
| myCustomDebugKeystoreField.setText(FileUtil.toSystemDependentName( |
| VfsUtil.urlToPath(configuration.getState().CUSTOM_DEBUG_KEYSTORE_PATH))); |
| |
| final boolean runProguard = configuration.getState().RUN_PROGUARD; |
| myRunProguardCheckBox.setSelected(runProguard); |
| myProGuardConfigFilesPanel.setUrls(configuration.getState().myProGuardCfgFiles); |
| |
| myUseCustomSourceDirectoryRadio.setSelected(configuration.getState().USE_CUSTOM_APK_RESOURCE_FOLDER); |
| myUseAptResDirectoryFromPathRadio.setSelected(!configuration.getState().USE_CUSTOM_APK_RESOURCE_FOLDER); |
| |
| String aptSourcePath = configuration.getState().CUSTOM_APK_RESOURCE_FOLDER; |
| String aptSourceAbsPath = aptSourcePath.length() > 0 ? toAbsolutePath(aptSourcePath) : ""; |
| myCustomAptSourceDirField.setText(aptSourceAbsPath != null ? aptSourceAbsPath : ""); |
| myCustomAptSourceDirField.setEnabled(configuration.getState().USE_CUSTOM_APK_RESOURCE_FOLDER); |
| |
| String apkPath = configuration.getState().APK_PATH; |
| String apkAbsPath = apkPath.length() > 0 ? toAbsolutePath(apkPath) : ""; |
| myApkPathCombo.getComboBox().getEditor().setItem(apkAbsPath != null ? apkAbsPath : ""); |
| |
| boolean mavenizedModule = AndroidMavenUtil.isMavenizedModule(myContext.getModule()); |
| myRunProcessResourcesRadio.setVisible(mavenizedModule); |
| myRunProcessResourcesRadio.setSelected(myConfiguration.getState().RUN_PROCESS_RESOURCES_MAVEN_TASK); |
| myCompileResourcesByIdeRadio.setVisible(mavenizedModule); |
| myCompileResourcesByIdeRadio.setSelected(!myConfiguration.getState().RUN_PROCESS_RESOURCES_MAVEN_TASK); |
| |
| myEnableManifestMerging.setSelected(myConfiguration.getState().ENABLE_MANIFEST_MERGING); |
| myPreDexEnabledCheckBox.setSelected(myConfiguration.getState().ENABLE_PRE_DEXING); |
| myIncludeTestCodeAndCheckBox.setSelected(myConfiguration.getState().PACK_TEST_CODE); |
| myIncludeAssetsFromLibraries.setSelected(myConfiguration.isIncludeAssetsFromLibraries()); |
| |
| myUseCustomManifestPackage.setSelected(myConfiguration.getState().USE_CUSTOM_MANIFEST_PACKAGE); |
| myCustomManifestPackageField.setEnabled(myConfiguration.getState().USE_CUSTOM_MANIFEST_PACKAGE); |
| myCustomManifestPackageField.setText(myConfiguration.getState().CUSTOM_MANIFEST_PACKAGE); |
| myAdditionalPackagingCommandLineParametersField.setText(myConfiguration.getState().ADDITIONAL_PACKAGING_COMMAND_LINE_PARAMETERS); |
| |
| String proguardLogsPath = configuration.getState().PROGUARD_LOGS_FOLDER_RELATIVE_PATH; |
| String proguardLogsAbsPath = proguardLogsPath.length() > 0 ? toAbsolutePath(proguardLogsPath) : ""; |
| myProguardLogsDirectoryField.setText(proguardLogsAbsPath != null ? proguardLogsAbsPath : ""); |
| |
| myUpdateProjectPropertiesCombo.setSelectedItem(myConfiguration.getState().UPDATE_PROPERTY_FILES); |
| myEnableSourcesAutogenerationCheckBox.setSelected(myConfiguration.getState().ENABLE_SOURCES_AUTOGENERATION); |
| updateAutogenerationPanels(); |
| |
| final int mavenTabIndex = myTabbedPane.indexOfTab(MAVEN_TAB_TITLE); |
| |
| if (mavenTabIndex >= 0) { |
| myTabbedPane.removeTabAt(mavenTabIndex); |
| } |
| |
| if (mavenizedModule) { |
| myTabbedPane.insertTab(MAVEN_TAB_TITLE, null, myMavenTabComponent, null, 2); |
| |
| for (int i = 0; i < myImportedOptionsList.getItemsCount(); i++) { |
| final AndroidImportableProperty property = (AndroidImportableProperty)myImportedOptionsList.getItemAt(i); |
| myImportedOptionsList.setItemSelected(property, configuration.isImportedProperty(property)); |
| } |
| } |
| updateLibAndAppSpecificFields(); |
| } |
| |
| @Nullable |
| private String toAbsolutePath(String genRelativePath) { |
| if (genRelativePath == null) { |
| return null; |
| } |
| if (genRelativePath.length() == 0) { |
| return ""; |
| } |
| String moduleDirPath = AndroidRootUtil.getModuleDirPath(myContext.getModule()); |
| if (moduleDirPath == null) return null; |
| final String path = PathUtil.getCanonicalPath(new File(moduleDirPath, genRelativePath).getPath()); |
| return path != null ? PathUtil.getLocalPath(path) : null; |
| } |
| |
| @Override |
| public void disposeUIResources() { |
| } |
| |
| private void createUIComponents() { |
| myProGuardConfigFilesPanel = new ProGuardConfigFilesPanel() { |
| @Nullable |
| @Override |
| protected AndroidFacet getFacet() { |
| return (AndroidFacet)myContext.getFacet(); |
| } |
| }; |
| } |
| |
| private class MyGenSourceFieldListener implements ActionListener { |
| private final TextFieldWithBrowseButton myTextField; |
| private final String myDefaultPath; |
| |
| private MyGenSourceFieldListener(TextFieldWithBrowseButton textField, String defaultPath) { |
| myTextField = textField; |
| myDefaultPath = defaultPath; |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| Module module = myContext.getModule(); |
| final VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); |
| |
| if (contentRoots.length == 0) { |
| return; |
| } |
| VirtualFile initialFile = null; |
| String path = myTextField.getText().trim(); |
| if (path.length() == 0) { |
| path = myDefaultPath; |
| } |
| if (path != null) { |
| initialFile = LocalFileSystem.getInstance().findFileByPath(path); |
| } |
| if (initialFile == null) { |
| ModuleRootManager manager = ModuleRootManager.getInstance(module); |
| VirtualFile[] sourceRoots = manager.getSourceRoots(); |
| if (sourceRoots.length > 0) { |
| initialFile = sourceRoots[0]; |
| } |
| else { |
| initialFile = module.getModuleFile(); |
| if (initialFile == null) { |
| String p = AndroidRootUtil.getModuleDirPath(myContext.getModule()); |
| if (p != null) { |
| initialFile = LocalFileSystem.getInstance().findFileByPath(p); |
| } |
| } |
| } |
| } |
| final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); |
| descriptor.setRoots(contentRoots); |
| VirtualFile file = FileChooser.chooseFile(descriptor, myContentPanel, myContext.getProject(), initialFile); |
| if (file != null) { |
| myTextField.setText(FileUtil.toSystemDependentName(file.getPath())); |
| } |
| } |
| } |
| |
| private class MyFolderFieldListener implements ActionListener { |
| private final TextFieldWithBrowseButton myTextField; |
| private final VirtualFile myDefaultDir; |
| private final boolean myChooseFile; |
| private final Condition<VirtualFile> myFilter; |
| |
| public MyFolderFieldListener(TextFieldWithBrowseButton textField, |
| VirtualFile defaultDir, |
| boolean chooseFile, |
| @Nullable Condition<VirtualFile> filter) { |
| myTextField = textField; |
| myDefaultDir = defaultDir; |
| myChooseFile = chooseFile; |
| myFilter = filter; |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| VirtualFile initialFile = null; |
| String path = myTextField.getText().trim(); |
| if (path.length() == 0) { |
| VirtualFile dir = myDefaultDir; |
| path = dir != null ? dir.getPath() : null; |
| } |
| if (path != null) { |
| initialFile = LocalFileSystem.getInstance().findFileByPath(path); |
| } |
| VirtualFile[] files = chooserDirsUnderModule(initialFile, myChooseFile, false, myFilter); |
| if (files.length > 0) { |
| assert files.length == 1; |
| myTextField.setText(FileUtil.toSystemDependentName(files[0].getPath())); |
| } |
| } |
| } |
| |
| private VirtualFile[] chooserDirsUnderModule(@Nullable VirtualFile initialFile, |
| final boolean chooseFile, |
| boolean chooseMultiple, |
| @Nullable final Condition<VirtualFile> filter) { |
| if (initialFile == null) { |
| initialFile = myContext.getModule().getModuleFile(); |
| } |
| if (initialFile == null) { |
| String p = AndroidRootUtil.getModuleDirPath(myContext.getModule()); |
| if (p != null) { |
| initialFile = LocalFileSystem.getInstance().findFileByPath(p); |
| } |
| } |
| final FileChooserDescriptor descriptor = new FileChooserDescriptor(chooseFile, !chooseFile, false, false, false, chooseMultiple) { |
| @Override |
| public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { |
| if (!super.isFileVisible(file, showHiddenFiles)) { |
| return false; |
| } |
| |
| if (!file.isDirectory() && !chooseFile) { |
| return false; |
| } |
| |
| return filter == null || filter.value(file); |
| } |
| }; |
| return FileChooser.chooseFiles(descriptor, myContentPanel, myContext.getProject(), initialFile); |
| } |
| |
| private static class MyManifestFilter implements Condition<VirtualFile> { |
| |
| @Override |
| public boolean value(VirtualFile file) { |
| return file.isDirectory() || file.getName().equals(SdkConstants.FN_ANDROID_MANIFEST_XML); |
| } |
| } |
| } |