aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:04:04 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:04:04 -0800
commit9ca1c0b33cc3fc28c21a915730797ec01e71a152 (patch)
tree86a5d0cea812248b02df654e925f55915e47bdf7 /eclipse
parent1506a206c0a5e3b593c4c61a62b8805b64e98daf (diff)
downloadsdk-9ca1c0b33cc3fc28c21a915730797ec01e71a152.zip
sdk-9ca1c0b33cc3fc28c21a915730797ec01e71a152.tar.gz
sdk-9ca1c0b33cc3fc28c21a915730797ec01e71a152.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/buildConfig/allElements.xml18
-rw-r--r--eclipse/changes.txt5
-rw-r--r--eclipse/features/com.android.ide.eclipse.adt/feature.xml28
-rw-r--r--eclipse/features/com.android.ide.eclipse.editors/.project17
-rw-r--r--eclipse/features/com.android.ide.eclipse.editors/build.properties1
-rw-r--r--eclipse/features/com.android.ide.eclipse.editors/feature.xml49
-rw-r--r--eclipse/features/com.android.ide.eclipse.platform/.project17
-rw-r--r--eclipse/features/com.android.ide.eclipse.platform/build.properties1
-rw-r--r--eclipse/features/com.android.ide.eclipse.platform/feature.xml52
-rw-r--r--eclipse/features/com.android.ide.eclipse.tests/feature.xml8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/.classpath7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF57
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/build.properties9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png)bin146 -> 146 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png)bin363 -> 363 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png)bin107 -> 107 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png)bin320 -> 320 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png)bin157 -> 157 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png)bin302 -> 302 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png)bin194 -> 194 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png)bin307 -> 307 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png)bin287 -> 287 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png)bin138 -> 138 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.pngbin0 -> 463 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png)bin265 -> 265 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png)bin308 -> 308 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png)bin325 -> 325 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/region.pngbin0 -> 445 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png)bin321 -> 321 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png)bin344 -> 344 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png)bin137 -> 137 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png (renamed from eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png)bin147 -> 147 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml187
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java670
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java71
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java86
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java45
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java41
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java210
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java11
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java91
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java152
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java49
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java111
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java104
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java57
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java35
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java345
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java275
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java291
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java332
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java266
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java)154
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java)19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java179
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java98
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java)33
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java285
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java)271
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java)6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java)28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java)88
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java24
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java282
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java)33
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java)64
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java)44
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java)117
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java)64
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java)9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java)34
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java)20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java)17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java (renamed from eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java)60
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java)215
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java)9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java)28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java)134
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java)6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java24
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java220
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java)852
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java65
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java)116
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java93
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java)20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java)157
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java244
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java142
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java)26
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java)31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java761
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java98
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java75
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java151
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java)60
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java345
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java)60
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java)23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java)34
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java)5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java)188
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java)97
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java)7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java)8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java)14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java)49
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java)37
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java)9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java)28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java)47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java)13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java)47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java)74
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java)23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java)5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java)38
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java)95
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java)12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java)40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java)6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java)28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java)14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java)6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java220
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java)7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java385
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java)24
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java)287
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java)2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java)90
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java)12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java)39
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java)20
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java)23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java)70
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java)12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java)7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java)107
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java)0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java (renamed from eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java)44
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/.classpath9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/.project28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF22
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/NOTICE224
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/build.properties7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/plugin.xml44
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java165
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java318
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/.classpath15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/.project28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF56
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/NOTICE224
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/build.properties10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/icons/android.pngbin3609 -> 0 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.pngbin6094 -> 0 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/icons/region.pngbin321 -> 0 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/icons/world.pngbin562 -> 0 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml107
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java672
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java87
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java124
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java405
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java199
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java157
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java298
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/.classpath7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/.project28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/NOTICE224
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/build.properties6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.pngbin138 -> 0 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml67
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java204
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java64
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java149
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java62
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java98
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java)8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java (renamed from eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java)7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java (renamed from eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java)16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java (renamed from eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java)36
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java3
-rwxr-xr-xeclipse/scripts/build_plugins.sh (renamed from eclipse/doBuild.sh)37
-rwxr-xr-xeclipse/scripts/build_server.sh17
-rwxr-xr-xeclipse/scripts/create_adt_symlinks.sh60
-rwxr-xr-xeclipse/scripts/create_all_symlinks.sh27
-rwxr-xr-xeclipse/scripts/create_bridge_symlinks.sh51
-rwxr-xr-xeclipse/scripts/create_common_symlinks.sh42
-rwxr-xr-xeclipse/scripts/create_ddms_symlinks.sh114
-rwxr-xr-xeclipse/scripts/create_editors_symlinks.sh39
-rwxr-xr-xeclipse/scripts/create_test_symlinks.sh56
-rw-r--r--eclipse/scripts/update_version.sh37
-rw-r--r--eclipse/sites/external/site.xml5
-rw-r--r--eclipse/sites/internal/site.xml16
326 files changed, 9571 insertions, 7102 deletions
diff --git a/eclipse/buildConfig/allElements.xml b/eclipse/buildConfig/allElements.xml
index 79f06df..99ab3aa 100644
--- a/eclipse/buildConfig/allElements.xml
+++ b/eclipse/buildConfig/allElements.xml
@@ -19,11 +19,6 @@
<property name="id" value="com.android.ide.eclipse.adt" />
</ant>
- <ant antfile="${genericTargets}" target="${target}">
- <property name="type" value="feature" />
- <property name="id" value="com.android.ide.eclipse.editors" />
- </ant>
-
<antcall target="buildInternalFeatures"/>
</target>
@@ -35,15 +30,10 @@
<target name="buildInternalFeatures" if="internalSite">
<ant antfile="${genericTargets}" target="${target}">
<property name="type" value="feature" />
- <property name="id" value="com.android.ide.eclipse.platform" />
- </ant>
- <ant antfile="${genericTargets}" target="${target}">
- <property name="type" value="feature" />
<property name="id" value="com.android.ide.eclipse.tests" />
</ant>
</target>
-
<!-- ===================================================================== -->
<!-- Targets to assemble the built elements for particular configurations -->
<!-- These generally call the generated assemble scripts (named in -->
@@ -55,14 +45,6 @@
<ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
</target>
- <target name="assemble.com.android.ide.eclipse.editors">
- <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
- </target>
-
- <target name="assemble.com.android.ide.eclipse.platform">
- <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
- </target>
-
<target name="assemble.com.android.ide.eclipse.tests">
<ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
</target>
diff --git a/eclipse/changes.txt b/eclipse/changes.txt
index bbe26de..5cb8245 100644
--- a/eclipse/changes.txt
+++ b/eclipse/changes.txt
@@ -1,3 +1,6 @@
+0.9.0 (work in progress)
+- Support for SDK with multiple versions of the Android platform and vendor supplied add-ons.
+
0.8.1:
- Alternate Layout wizard. In the layout editor, the "create" button is now enabled, and allows to easily create alternate versions.
@@ -5,6 +8,8 @@
- Export Wizard: To export an application for release, sign with a non debug key. Accessible from the export menu, from the Android Tools contextual menu, or from the overview page of the manifest editor.
- New XML File Wizard: To easily create new XML resources file in the /res directory.
- New checks on launch when attempting to debug on a device.
+- Basic support for drag'n'drop in Graphical layout editor. You can add new items by drag'n'drop from the palette. There's is no support for moving/resizing yet.
+- Undo/redo support in all XML form editors and Graphical layout editor.
0.8.0:
diff --git a/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index f8356b0..191b76d 100644
--- a/eclipse/features/com.android.ide.eclipse.adt/feature.xml
+++ b/eclipse/features/com.android.ide.eclipse.adt/feature.xml
@@ -2,7 +2,7 @@
<feature
id="com.android.ide.eclipse.adt"
label="Android Development Tools"
- version="0.8.1.qualifier"
+ version="0.9.0.qualifier"
provider-name="The Android Open Source Project"
plugin="com.android.ide.eclipse.adt">
@@ -14,37 +14,35 @@
Copyright (C) 2007 The Android Open Source Project
</copyright>
+ <license>
+ License TBD.
+ </license>
+
<url>
<update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
</url>
<requires>
- <import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.console"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.editors"/>
+ <import plugin="org.eclipse.core.resources"/>
<import plugin="org.eclipse.debug.core"/>
<import plugin="org.eclipse.debug.ui"/>
<import plugin="org.eclipse.jdt"/>
<import plugin="org.eclipse.ant.core"/>
+ <import plugin="org.eclipse.jdt.core"/>
+ <import plugin="org.eclipse.jdt.ui"/>
<import plugin="org.eclipse.jdt.launching"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.editors"/>
<import plugin="org.eclipse.ui.workbench.texteditor"/>
+ <import plugin="org.eclipse.ui.console"/>
<import plugin="org.eclipse.core.filesystem"/>
+ <import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.ui.forms"/>
</requires>
<plugin
- id="com.android.ide.eclipse.common"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
id="com.android.ide.eclipse.adt"
download-size="0"
install-size="0"
diff --git a/eclipse/features/com.android.ide.eclipse.editors/.project b/eclipse/features/com.android.ide.eclipse.editors/.project
deleted file mode 100644
index a960976..0000000
--- a/eclipse/features/com.android.ide.eclipse.editors/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>editors-feature</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.pde.FeatureBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.FeatureNature</nature>
- </natures>
-</projectDescription>
diff --git a/eclipse/features/com.android.ide.eclipse.editors/build.properties b/eclipse/features/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/eclipse/features/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/eclipse/features/com.android.ide.eclipse.editors/feature.xml b/eclipse/features/com.android.ide.eclipse.editors/feature.xml
deleted file mode 100644
index f5f92e8..0000000
--- a/eclipse/features/com.android.ide.eclipse.editors/feature.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
- id="com.android.ide.eclipse.editors"
- label="Android Editors"
- version="0.8.1.qualifier"
- provider-name="The Android Open Source Project"
- plugin="com.android.ide.eclipse.editors">
-
- <description>
- This feature provides Editors for Android files.
- </description>
-
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
- </copyright>
-
- <url>
- <update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
- </url>
-
- <requires>
- <import plugin="com.android.ide.eclipse.common"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.core.resources"/>
- <import plugin="org.eclipse.ui.editors"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.ide"/>
- <import plugin="org.eclipse.wst.sse.ui"/>
- <import plugin="org.eclipse.wst.xml.ui"/>
- <import plugin="org.eclipse.wst.xml.core"/>
- <import plugin="org.eclipse.wst.sse.core"/>
- <import plugin="org.eclipse.ui.forms"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.browser"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.gef"/>
- <import plugin="org.eclipse.ui.views"/>
- <import plugin="org.eclipse.ui.console"/>
- </requires>
-
- <plugin
- id="com.android.ide.eclipse.editors"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
-</feature>
diff --git a/eclipse/features/com.android.ide.eclipse.platform/.project b/eclipse/features/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 0bb8c34..0000000
--- a/eclipse/features/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>platform-feature</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.pde.FeatureBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.FeatureNature</nature>
- </natures>
-</projectDescription>
diff --git a/eclipse/features/com.android.ide.eclipse.platform/build.properties b/eclipse/features/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/eclipse/features/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/eclipse/features/com.android.ide.eclipse.platform/feature.xml b/eclipse/features/com.android.ide.eclipse.platform/feature.xml
deleted file mode 100644
index aa4b166..0000000
--- a/eclipse/features/com.android.ide.eclipse.platform/feature.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
- id="com.android.ide.eclipse.platform"
- label="Android Platform Tools"
- version="0.8.1.qualifier"
- provider-name="The Android Open Source Project">
-
- <description>
- This feature provides a ddms perspective and editor functionnality for Android.
- </description>
-
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
- </copyright>
-
- <url>
- <update label="Android Update Site" url="https://android.corp.google.com/adt/"/>
- </url>
-
- <requires>
- <import plugin="org.eclipse.core.resources"/>
- <import plugin="org.eclipse.core.runtime"/>
- <import plugin="org.eclipse.jdt.core"/>
- <import plugin="org.eclipse.ui.console"/>
- <import plugin="org.eclipse.ui"/>
- <import plugin="org.eclipse.jdt.ui"/>
- <import plugin="org.eclipse.jface.text"/>
- <import plugin="org.eclipse.ui.editors"/>
- </requires>
-
- <plugin
- id="com.android.ide.eclipse.common"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
- id="com.android.ide.eclipse.platform"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
- <plugin
- id="com.android.ide.eclipse.ddms"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
-
-</feature>
diff --git a/eclipse/features/com.android.ide.eclipse.tests/feature.xml b/eclipse/features/com.android.ide.eclipse.tests/feature.xml
index b5a848c..2a3a74f 100644
--- a/eclipse/features/com.android.ide.eclipse.tests/feature.xml
+++ b/eclipse/features/com.android.ide.eclipse.tests/feature.xml
@@ -2,11 +2,11 @@
<feature
id="com.android.ide.eclipse.tests"
label="ADT Tests"
- version="0.8.1.qualifier"
+ version="0.9.0.qualifier"
provider-name="The Android Open Source Project">
- <copyright>
- Copyright (C) 2007 The Android Open Source Project
+ <copyright>
+ Copyright (C) 2007 The Android Open Source Project
</copyright>
<requires>
@@ -15,8 +15,6 @@
<import plugin="org.eclipse.core.resources"/>
<import plugin="com.android.ide.eclipse.adt"/>
<import plugin="org.junit"/>
- <import plugin="com.android.ide.eclipse.common"/>
- <import plugin="com.android.ide.eclipse.editors"/>
<import plugin="org.eclipse.jdt.core"/>
<import plugin="org.eclipse.jdt.launching"/>
<import plugin="org.eclipse.ui.views"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index 4dd4cac..bbcdff9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -5,5 +5,12 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="jarutils.jar"/>
<classpathentry kind="lib" path="androidprefs.jar"/>
+ <classpathentry kind="lib" path="sdkstats.jar"/>
+ <classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
+ <classpathentry kind="lib" path="layoutlib_api.jar"/>
+ <classpathentry kind="lib" path="layoutlib_utils.jar"/>
+ <classpathentry kind="lib" path="ninepatch.jar"/>
+ <classpathentry kind="lib" path="sdklib.jar"/>
+ <classpathentry kind="lib" path="sdkuilib.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 9926074..a464d5c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -2,14 +2,20 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Android Development Toolkit
Bundle-SymbolicName: com.android.ide.eclipse.adt;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-ClassPath: .,
jarutils.jar,
- androidprefs.jar
+ androidprefs.jar,
+ sdkstats.jar,
+ kxml2-2.3.0.jar,
+ layoutlib_api.jar,
+ ninepatch.jar,
+ layoutlib_utils.jar,
+ sdklib.jar,
+ sdkuilib.jar
Bundle-Activator: com.android.ide.eclipse.adt.AdtPlugin
Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- com.android.ide.eclipse.ddms,
+Require-Bundle: com.android.ide.eclipse.ddms,
org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.debug.core,
@@ -26,11 +32,48 @@ Require-Bundle: com.android.ide.eclipse.common,
org.eclipse.core.filesystem,
org.eclipse.ui,
org.eclipse.ui.ide,
- org.eclipse.ui.forms
+ org.eclipse.ui.forms,
+ org.eclipse.gef,
+ org.eclipse.ui.browser,
+ org.eclipse.ui.views,
+ org.eclipse.wst.sse.core,
+ org.eclipse.wst.sse.ui,
+ org.eclipse.wst.xml.core,
+ org.eclipse.wst.xml.ui
Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
+Export-Package: com.android.ide.eclipse.adt,
+ com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests",
com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.adt.resources;x-friends:="com.android.ide.eclipse.tests"
+ com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.adt.wizards.newproject;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.common,
+ com.android.ide.eclipse.common.project,
+ com.android.ide.eclipse.common.resources,
+ com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/build.properties b/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
index 6d6c2e8..c7eb749 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
@@ -5,6 +5,13 @@ bin.includes = plugin.xml,\
templates/,\
about.ini,\
jarutils.jar,\
- androidprefs.jar
+ androidprefs.jar,\
+ sdkstats.jar,\
+ kxml2-2.3.0.jar,\
+ layoutlib_api.jar,\
+ layoutlib_utils.jar,\
+ ninepatch.jar,\
+ sdklib.jar,\
+ sdkuilib.jar
source.. = src/
output.. = bin/
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
index eefc2ca..eefc2ca 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
index 5d92f76..5d92f76 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
index db5fab8..db5fab8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
index 10057c8..10057c8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
index 36cd223..36cd223 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
index fae5e96..fae5e96 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
index 1eecf2c..1eecf2c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
index 7911a85..7911a85 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
index a727dd5..a727dd5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
index 7e939c2..7e939c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
new file mode 100644
index 0000000..4dc95d7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
index aefffe4..aefffe4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
index c2bb79a..c2bb79a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
index 423c3cd..423c3cd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
new file mode 100644
index 0000000..9608cd6
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
index b4ddc87..b4ddc87 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
index 6536576..6536576 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
index 35b9a46..35b9a46 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
index ca3b6ed..ca3b6ed 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 51b1291..ade4646 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -2,6 +2,38 @@
<?eclipse version="3.2"?>
<plugin>
<extension
+ id="com.android.ide.eclipse.common.xmlProblem"
+ name="Android XML Format Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.aaptProblem"
+ name="Android AAPT Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.aidlProblem"
+ name="Android AIDL Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="com.android.ide.eclipse.common.androidProblem"
+ name="Android XML Content Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <super type="org.eclipse.core.resources.textmarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
id="ResourceManagerBuilder"
name="Android Resource Manager"
point="org.eclipse.core.resources.builders">
@@ -47,7 +79,7 @@
<wizard
canFinishEarly="false"
category="com.android.ide.eclipse.wizards.category"
- class="com.android.ide.eclipse.adt.project.internal.NewProjectWizard"
+ class="com.android.ide.eclipse.adt.wizards.newproject.NewProjectWizard"
finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
hasPages="true"
icon="icons/android.png"
@@ -55,6 +87,18 @@
name="Android Project"
preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
project="true"/>
+ <wizard
+ canFinishEarly="false"
+ category="com.android.ide.eclipse.wizards.category"
+ class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+ finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
+ hasPages="true"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+ name="Android XML File"
+ preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
+ project="false">
+ </wizard>
</extension>
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
@@ -174,6 +218,13 @@
label="Create Aidl preprocess file for Parcelable classes"
menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1"/>
<action
+ class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+ enablesFor="1"
+ id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+ label="New Resource File..."
+ menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1">
+ </action>
+ <action
class="com.android.ide.eclipse.adt.project.ExportAction"
enablesFor="1"
id="com.android.ide.eclipse.adt.project.ExportAction"
@@ -183,7 +234,7 @@
class="com.android.ide.eclipse.adt.project.ExportWizardAction"
enablesFor="1"
id="com.android.ide.eclipse.adt.project.ExportWizardAction"
- label="Export Application..."
+ label="Export Signed Application Package..."
menubarPath="com.android.ide.eclipse.adt.AndroidTools/group2"/>
<action
class="com.android.ide.eclipse.adt.project.FixProjectAction"
@@ -209,30 +260,32 @@
class="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
id="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
name="Launch"/>
+ <page
+ category="com.android.ide.eclipse.preferences.main"
+ class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+ id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+ name="Usage Stats">
+ </page>
</extension>
<extension
point="org.eclipse.core.runtime.preferences">
<initializer class="com.android.ide.eclipse.adt.preferences.PreferenceInitializer"/>
</extension>
<extension
- point="org.eclipse.ui.editors">
- <editor
- class="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
- contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
- default="true"
- filenames="R.java, Manifest.java"
- icon="icons/android.png"
- id="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
- name="Android Java Editor"/>
- </extension>
- <extension
id="com.android.ide.eclipse.adt.adtProblem"
- name="Generic ADT Problem"
+ name="Android ADT Problem"
point="org.eclipse.core.resources.markers">
<super type="org.eclipse.core.resources.problemmarker"/>
<persistent value="true"/>
</extension>
<extension
+ id="com.android.ide.eclipse.adt.targetProblem"
+ name="Android Target Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.core.resources.problemmarker"/>
+ <persistent value="false"/>
+ </extension>
+ <extension
point="org.eclipse.ui.perspectiveExtensions">
<perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
<newWizardShortcut id="com.android.ide.eclipse.adt.project.NewProjectWizard" />
@@ -305,4 +358,110 @@
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
</keyBinding>
</extension>
+ <extension
+ point="org.eclipse.ui.decorators">
+ <decorator
+ adaptable="true"
+ class="com.android.ide.eclipse.adt.project.FolderDecorator"
+ id="com.android.ide.eclipse.adt.project.FolderDecorator"
+ label="Android Decorator"
+ lightweight="true"
+ location="TOP_RIGHT"
+ objectClass="org.eclipse.core.resources.IFolder"
+ state="true">
+ </decorator>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+ default="true"
+ filenames="AndroidManifest.xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+ name="Android Manifest Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+ name="Android Resource Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.layout.LayoutEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.layout.LayoutEditor"
+ matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
+ name="Android Layout Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.menu.MenuEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.menu.MenuEditor"
+ name="Android Menu Editor">
+ </editor>
+ <editor
+ class="com.android.ide.eclipse.editors.xml.XmlEditor"
+ default="false"
+ extensions="xml"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.xml.XmlEditor"
+ name="Android Xml Resources Editor">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ allowMultiple="false"
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+ icon="icons/android.png"
+ id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+ name="Resource Explorer">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.ui.editorConfiguration">
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.layout.LayoutEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.menu.MenuEditor">
+ </sourceViewerConfiguration>
+ <sourceViewerConfiguration
+ class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
+ target="com.android.ide.eclipse.editors.xml.XmlEditor">
+ </sourceViewerConfiguration>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ adaptable="true"
+ class="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+ id="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+ name="Android"
+ nameFilter="*"
+ objectClass="org.eclipse.core.resources.IProject">
+ <enabledWhen>
+ <test property="org.eclipse.jdt.launching.hasProjectNature"
+ args="com.android.ide.eclipse.adt.AndroidNature"/>
+ </enabledWhen>
+ </page>
+ </extension>
</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 6d52aa5..61b3f4d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt;
+
/**
* Constant definition class.<br>
* <br>
@@ -39,6 +40,12 @@ public class AdtConstants {
/** Generic marker for ADT errors. */
public final static String MARKER_ADT = AdtPlugin.PLUGIN_ID + ".adtProblem"; //$NON-NLS-1$
+ /** Marker for Android Target errors.
+ * This is not cleared on each like other markers. Instead, it's cleared
+ * when a ContainerClasspathInitialized has succeeded in creating an
+ * {@link AndroidClasspathContainer}*/
+ public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$
+
/** Build verbosity "Always". Those messages are always displayed. */
public final static int BUILD_ALWAYS = 0;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 9b24b07..d9c18cf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -22,34 +22,55 @@ import com.android.ddmuilib.console.DdmConsole;
import com.android.ddmuilib.console.IDdmConsole;
import com.android.ide.eclipse.adt.build.DexWrapper;
import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
import com.android.ide.eclipse.adt.preferences.BuildPreferencePage;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.project.export.ExportWizard;
import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
-import com.android.ide.eclipse.adt.resources.FrameworkResourceParser;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetParser;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.EclipseUiHelper;
import com.android.ide.eclipse.common.SdkStatsHelper;
import com.android.ide.eclipse.common.StreamHelper;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.ExportHelper;
import com.android.ide.eclipse.common.project.ExportHelper.IExportCallback;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.ide.eclipse.ddms.ImageLoader;
-
+import com.android.ide.eclipse.editors.IconFactory;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.menu.MenuEditor;
+import com.android.ide.eclipse.editors.resources.ResourcesEditor;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
+import com.android.ide.eclipse.editors.xml.XmlEditor;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
@@ -57,14 +78,21 @@ import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -81,6 +109,8 @@ import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* The activator class controls the plug-in life cycle
@@ -106,14 +136,17 @@ public class AdtPlugin extends AbstractUIPlugin {
/** singleton instance */
private static AdtPlugin sPlugin;
+ private static Image sAndroidLogo;
+ private static ImageDescriptor sAndroidLogoDesc;
+
/** default store, provided by eclipse */
private IPreferenceStore mStore;
/** cached location for the sdk folder */
private String mOsSdkLocation;
- /** SDK Api Version */
- String mSdkApiVersion;
+ /** The global android console */
+ private MessageConsole mAndroidConsole;
/** Stream to write in the android console */
private MessageConsoleStream mAndroidConsoleStream;
@@ -130,14 +163,14 @@ public class AdtPlugin extends AbstractUIPlugin {
/** Color used in the error console */
private Color mRed;
- private final ArrayList<IJavaProject> mPostDexProjects = new ArrayList<IJavaProject>();
+ /** Load status of the SDK. Any access MUST be in a synchronized(mPostLoadProjects) block */
+ private LoadStatus mSdkIsLoaded = LoadStatus.LOADING;
+ /** Project to update once the SDK is loaded.
+ * Any access MUST be in a synchronized(mPostLoadProjects) block */
+ private final ArrayList<IJavaProject> mPostLoadProjects = new ArrayList<IJavaProject>();
- /** Boolean wrapper to run dialog in the UI thread, and still get the
- * return code.
- */
- private static final class BooleanWrapper {
- public boolean b;
- }
+ private ResourceMonitor mResourceMonitor;
+ private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
/**
* Custom PrintStream for Dx output. This class overrides the method
@@ -210,10 +243,14 @@ public class AdtPlugin extends AbstractUIPlugin {
Display display = getDisplay();
+ // set the default android console.
+ mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
+ ConsolePlugin.getDefault().getConsoleManager().addConsoles(
+ new IConsole[] { mAndroidConsole });
+
// get the stream to write in the android console.
- MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
- mAndroidConsoleStream = androidConsole.newMessageStream();
- mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+ mAndroidConsoleStream = mAndroidConsole.newMessageStream();
+ mAndroidConsoleErrorStream = mAndroidConsole.newMessageStream();
mRed = new Color(display, 0xFF, 0x00, 0x00);
// because this can be run, in some cases, by a non ui thread, and beccause
@@ -267,22 +304,19 @@ public class AdtPlugin extends AbstractUIPlugin {
// get the SDK location and build id.
if (checkSdkLocationAndId()) {
- // if sdk if valid, reparse the skin folder
- SkinRepository.getInstance().parseFolder(getOsSkinFolder());
+ // if sdk if valid, reparse it
+
+ // add the current Android project to the list of projects to be updated
+ // after the SDK is reloaded
+ synchronized (mPostLoadProjects) {
+ // get the project to refresh.
+ IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
+ mPostLoadProjects.addAll(Arrays.asList(androidProjects));
+ }
+
+ // parse the SDK resources at the new location
+ parseSdkContent();
}
-
- // parse the SDK resources at the new location
- parseSdkContent();
-
- // get the project to refresh.
- IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
-
- // Setup the new container for each project. By providing new instances of
- // AndroidClasspathContainer, this will force JDT to call
- // IClasspathContainer#getClasspathEntries() again and receive the new
- // path to the framework jar.
- AndroidClasspathContainerInitializer.updateProjects(androidProjects);
-
} else if (PREFS_BUILD_VERBOSITY.equals(property)) {
mBuildVerbosity = BuildPreferencePage.getBuildLevel(
mStore.getString(PREFS_BUILD_VERBOSITY));
@@ -299,20 +333,11 @@ public class AdtPlugin extends AbstractUIPlugin {
}
// check the location of SDK
- if (checkSdkLocationAndId()) {
- // if sdk if valid, parse the skin folder
- SkinRepository.getInstance().parseFolder(getOsSkinFolder());
-
- // parse the SDK resources.
- parseSdkContent();
- }
+ final boolean isSdkLocationValid = checkSdkLocationAndId();
mBuildVerbosity = BuildPreferencePage.getBuildLevel(
mStore.getString(PREFS_BUILD_VERBOSITY));
- // Ping the usage start server.
- pingUsageServer();
-
// create the loader that's able to load the images
mLoader = new ImageLoader(this);
@@ -356,18 +381,31 @@ public class AdtPlugin extends AbstractUIPlugin {
dialog.open();
}
});
-
- /* The Editors plugin must be started as soon as Android projects are opened or created,
- * in order to properly set default editors on the layout/values XML files.
- *
- * This ensures that the default editors is really only set when a new XML file
- * is added to the workspace (IResourceDelta.ADDED event), through project creation or
- * manual add.
- * Other methods would force to go through existing projects when the Editors plugin is
- * started, and set the default editors for their XML files, possibly erasing user set
- * default editors.
- */
- startEditorsPlugin();
+
+ // initialize editors
+ startEditors();
+
+ // Ping the usage server and parse the SDK content.
+ // This is deferred in separate jobs to avoid blocking the bundle start.
+ // We also serialize them to avoid too many parallel jobs when Eclipse starts.
+ Job pingJob = createPingUsageServerJob();
+ pingJob.addJobChangeListener(new JobChangeAdapter() {
+ @Override
+ public void done(IJobChangeEvent event) {
+ super.done(event);
+
+ // Once the ping job is finished, start the SDK parser
+ if (isSdkLocationValid) {
+ // parse the SDK resources.
+ parseSdkContent();
+ }
+ }
+ });
+ // build jobs are run after other interactive jobs
+ pingJob.setPriority(Job.BUILD);
+ // Wait 2 seconds before starting the ping job. This leaves some time to the
+ // other bundles to initialize.
+ pingJob.schedule(2000 /*milliseconds*/);
}
/*
@@ -379,6 +417,8 @@ public class AdtPlugin extends AbstractUIPlugin {
public void stop(BundleContext context) throws Exception {
super.stop(context);
+ stopEditors();
+
DexWrapper.unloadDex();
mRed.dispose();
@@ -418,37 +458,22 @@ public class AdtPlugin extends AbstractUIPlugin {
/** Returns the adb path relative to the sdk folder */
public static String getOsRelativeAdb() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
}
/** Returns the aapt path relative to the sdk folder */
public static String getOsRelativeAapt() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
}
/** Returns the emulator path relative to the sdk folder */
public static String getOsRelativeEmulator() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
}
/** Returns the aidl path relative to the sdk folder */
public static String getOsRelativeAidl() {
- return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
- }
-
- /** Returns the framework jar path relative to the sdk folder */
- public static String getOsRelativeFramework() {
- return AndroidConstants.FN_FRAMEWORK_LIBRARY;
- }
-
- /** Returns the android sources path relative to the sdk folder */
- public static String getOsRelativeAndroidSources() {
- return AndroidConstants.FD_ANDROID_SOURCES;
- }
-
- /** Returns the framework jar path relative to the sdk folder */
- public static String getOsRelativeAttrsXml() {
- return AndroidConstants.OS_SDK_LIBS_FOLDER + AndroidConstants.FN_ATTRS_XML;
+ return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
}
/** Returns the absolute adb path */
@@ -458,7 +483,7 @@ public class AdtPlugin extends AbstractUIPlugin {
/** Returns the absolute traceview path */
public static String getOsAbsoluteTraceview() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER +
+ return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER +
AndroidConstants.FN_TRACEVIEW;
}
@@ -467,21 +492,6 @@ public class AdtPlugin extends AbstractUIPlugin {
return getOsSdkFolder() + getOsRelativeAapt();
}
- /** Returns the absolute sdk framework path */
- public static String getOsAbsoluteFramework() {
- return getOsSdkFolder() + getOsRelativeFramework();
- }
-
- /** Returns the absolute android sources path in the sdk */
- public static String getOsAbsoluteAndroidSources() {
- return getOsSdkFolder() + getOsRelativeAndroidSources();
- }
-
- /** Returns the absolute attrs.xml path */
- public static String getOsAbsoluteAttrsXml() {
- return getOsSdkFolder() + getOsRelativeAttrsXml();
- }
-
/** Returns the absolute emulator path */
public static String getOsAbsoluteEmulator() {
return getOsSdkFolder() + getOsRelativeEmulator();
@@ -492,16 +502,6 @@ public class AdtPlugin extends AbstractUIPlugin {
return getOsSdkFolder() + getOsRelativeAidl();
}
- /** Returns the absolute path to the aidl framework import file. */
- public static String getOsAbsoluteFrameworkAidl() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_LIBS_FOLDER +
- AndroidConstants.FN_FRAMEWORK_AIDL;
- }
-
- public static String getOsSdkSamplesFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_SAMPLES_FOLDER;
- }
-
/**
* Returns a Url file path to the javaDoc folder.
*/
@@ -526,11 +526,7 @@ public class AdtPlugin extends AbstractUIPlugin {
}
public static String getOsSdkToolsFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER;
- }
-
- public static String getOsSkinFolder() {
- return getOsSdkFolder() + AndroidConstants.OS_SDK_SKINS_FOLDER;
+ return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER;
}
public static synchronized boolean getAutoResRefresh() {
@@ -540,18 +536,6 @@ public class AdtPlugin extends AbstractUIPlugin {
return sPlugin.mStore.getBoolean(PREFS_RES_AUTO_REFRESH);
}
- /**
- * Returns the SDK build id.
- * @return a string containing the SDK build id, or null it it is unknownn.
- */
- public static synchronized String getSdkApiVersion() {
- if (sPlugin != null) {
- return sPlugin.mSdkApiVersion;
- }
-
- return null;
- }
-
public static synchronized int getBuildVerbosity() {
if (sPlugin != null) {
return sPlugin.mBuildVerbosity;
@@ -705,23 +689,25 @@ public class AdtPlugin extends AbstractUIPlugin {
final Display display = getDisplay();
// we need to ask the user what he wants to do.
- final BooleanWrapper wrapper = new BooleanWrapper();
+ final boolean[] result = new boolean[1];
display.syncExec(new Runnable() {
public void run() {
Shell shell = display.getActiveShell();
- wrapper.b = MessageDialog.openQuestion(shell, title, message);
+ result[0] = MessageDialog.openQuestion(shell, title, message);
}
});
- return wrapper.b;
+ return result[0];
}
/**
* Logs a message to the default Eclipse log.
*
- * @param severity The severity code. Valid values are: {@link IStatus#OK}, {@link IStatus#ERROR},
- * {@link IStatus#INFO}, {@link IStatus#WARNING} or {@link IStatus#CANCEL}.
+ * @param severity The severity code. Valid values are: {@link IStatus#OK},
+ * {@link IStatus#ERROR}, {@link IStatus#INFO}, {@link IStatus#WARNING} or
+ * {@link IStatus#CANCEL}.
* @param format The format string, like for {@link String#format(String, Object...)}.
- * @param args The arguments for the format string, like for {@link String#format(String, Object...)}.
+ * @param args The arguments for the format string, like for
+ * {@link String#format(String, Object...)}.
*/
public static void log(int severity, String format, Object ... args) {
String message = String.format(format, args);
@@ -845,7 +831,7 @@ public class AdtPlugin extends AbstractUIPlugin {
// now make sure it's not docked.
ConsolePlugin.getDefault().getConsoleManager().showConsoleView(
- CommonPlugin.getDefault().getAndroidConsole());
+ AdtPlugin.getDefault().getAndroidConsole());
}
/**
@@ -883,21 +869,17 @@ public class AdtPlugin extends AbstractUIPlugin {
}
/**
- * Adds a {@link IJavaProject} to a list of projects to be recompiled once dx.jar is loaded.
- * @param javaProject
+ * Returns whether the Sdk has been loaded. If the SDK has not been loaded, the given
+ * <var>project</var> is added to a list of projects to recompile after the SDK is loaded.
*/
- public void addPostDexProject(IJavaProject javaProject) {
- synchronized (mPostDexProjects) {
- if (DexWrapper.getStatus() == DexWrapper.LoadStatus.LOADED) {
- // Setup the new container for each project. By providing new instances of
- // AndroidClasspathContainer, this will force JDT to call
- // IClasspathContainer#getClasspathEntries() again and receive the new
- // path to the framework jar, and the project will be recompiled.
- AndroidClasspathContainerInitializer.updateProjects(new IJavaProject [] {
- javaProject });
- } else {
- mPostDexProjects.add(javaProject);
+ public LoadStatus getSdkLoadStatus(IJavaProject project) {
+ synchronized (mPostLoadProjects) {
+ // only add the project to the list, if we are still loading.
+ if (mSdkIsLoaded == LoadStatus.LOADING && project != null) {
+ mPostLoadProjects.add(project);
}
+
+ return mSdkIsLoaded;
}
}
@@ -907,9 +889,6 @@ public class AdtPlugin extends AbstractUIPlugin {
* @return false if the location is not correct.
*/
private boolean checkSdkLocationAndId() {
- // Reset the sdk build first in case the SDK is invalid and we abort.
- mSdkApiVersion = null;
-
if (mOsSdkLocation == null || mOsSdkLocation.length() == 0) {
displayError(Messages.Dialog_Title_SDK_Location, Messages.SDK_Not_Setup);
return false;
@@ -949,17 +928,16 @@ public class AdtPlugin extends AbstractUIPlugin {
String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
}
- String osTools = osSdkLocation + AndroidConstants.OS_SDK_TOOLS_FOLDER;
+ String osTools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
File toolsFolder = new File(osTools);
if (toolsFolder.isDirectory() == false) {
return errorHandler.handleError(
String.format(Messages.Could_Not_Find_Folder_In_SDK,
- AndroidConstants.FD_TOOLS, osSdkLocation));
+ SdkConstants.FD_TOOLS, osSdkLocation));
}
// check the path to various tools we use
String[] filesToCheck = new String[] {
- osSdkLocation + getOsRelativeFramework(),
osSdkLocation + getOsRelativeAdb(),
osSdkLocation + getOsRelativeAapt(),
osSdkLocation + getOsRelativeAidl(),
@@ -990,118 +968,106 @@ public class AdtPlugin extends AbstractUIPlugin {
}
/**
- * Pings the usage start server.
+ * Creates a job than can ping the usage server.
*/
- private void pingUsageServer() {
+ private Job createPingUsageServerJob() {
// In order to not block the plugin loading, so we spawn another thread.
- new Thread("Ping!") { //$NON-NLS-1$
+ Job job = new Job("Android SDK Ping") { // Job name, visible in progress view
@Override
- public void run() {
- // get the version of the plugin
- String versionString = (String) getBundle().getHeaders().get(
- Constants.BUNDLE_VERSION);
- Version version = new Version(versionString);
-
- SdkStatsHelper.pingUsageServer("adt", version); //$NON-NLS-1$
- }
- }.start();
- }
-
- /**
- * Starts the Editors plugin.
- * <p/>
- * Since we do not want any dependencies between the plugins (Editors is an optional
- * plugin not needed for Android development), we attempt to start the plugin through
- * OSGi directly.
- * <p/>
- * This is done in another thread to not delay the start of this plugin.
- */
- private void startEditorsPlugin() {
- new Thread() {
- @Override
- public void run() {
+ protected IStatus run(IProgressMonitor monitor) {
try {
- // look for the bundle of the Editors plugin
- Bundle editorsBundle = Platform.getBundle(AndroidConstants.EDITORS_PLUGIN_ID);
- if (editorsBundle != null) {
- // we only start if the bundle is installed and not started.
- // STARTING means that its start is pending a triggering.
- int bundleState = editorsBundle.getState();
- if ((bundleState & (Bundle.RESOLVED | Bundle.INSTALLED
- | Bundle.STARTING)) != 0) {
- // Attempt to start it.
- // START_TRANSIENT is used because we don't want
- // to change the auto start value.
- editorsBundle.start(Bundle.START_TRANSIENT);
- }
- }
- } catch (Exception e) {
- log(e, Messages.AdtPlugin_Failed_To_Start_s, AndroidConstants.EDITORS_PLUGIN_ID);
+
+ // get the version of the plugin
+ String versionString = (String) getBundle().getHeaders().get(
+ Constants.BUNDLE_VERSION);
+ Version version = new Version(versionString);
+
+ SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
+
+ return Status.OK_STATUS;
+ } catch (Throwable t) {
+ log(t, "pingUsageServer failed"); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, PLUGIN_ID,
+ "pingUsageServer failed", t);
}
}
- }.start();
+ };
+ return job;
}
/**
- * Parses the SDK resources and set them in the {@link FrameworkResourceManager}.
+ * Parses the SDK resources.
*/
private void parseSdkContent() {
// Perform the update in a thread (here an Eclipse runtime job)
// since this should never block the caller (especially the start method)
- new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+ Job job = new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+ @SuppressWarnings("unchecked")
@Override
protected IStatus run(IProgressMonitor monitor) {
- try {
- SubMonitor progress = null;
- try {
- progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 100);
+ try {
+ SubMonitor progress = SubMonitor.convert(monitor,
+ "Initialize SDK Manager", 100);
+
+ Sdk sdk = Sdk.loadSdk(mOsSdkLocation);
+
+ if (sdk != null) {
- // load the values.
- FrameworkResourceParser parser = new FrameworkResourceParser();
- parser.parse(mOsSdkLocation, FrameworkResourceManager.getInstance(),
- progress);
-
- // set the location of the layout lib jar file.
- FrameworkResourceManager.getInstance().setLayoutLibLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_LAYOUTLIB_JAR);
- FrameworkResourceManager.getInstance().setFrameworkResourcesLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_RESOURCES_FOLDER);
- FrameworkResourceManager.getInstance().setFrameworkFontLocation(
- mOsSdkLocation + AndroidConstants.OS_SDK_FONTS_FOLDER);
- } catch (Throwable e) {
- AdtPlugin.log(e, "Android SDK Resource Parser failed"); //$NON-NLS-1$
- AdtPlugin.printErrorToConsole(Messages.AdtPlugin_Android_SDK_Resource_Parser,
- Messages.AdtPlugin_Failed_To_Parse_s + e.getMessage());
+ progress.setTaskName(Messages.AdtPlugin_Parsing_Resources);
- return new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage(), e);
- } finally {
- if (progress != null) {
- progress.worked(100);
+ for (IAndroidTarget target : sdk.getTargets()) {
+ IStatus status = new AndroidTargetParser(target).run(progress);
+ if (status.getCode() != IStatus.OK) {
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.FAILED;
+ mPostLoadProjects.clear();
+ }
+ return status;
+ }
}
- }
-
- try {
- progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 20);
+
+ // FIXME: move this per platform, or somewhere else.
+ progress = SubMonitor.convert(monitor,
+ Messages.AdtPlugin_Parsing_Resources, 20);
DexWrapper.unloadDex();
IStatus res = DexWrapper.loadDex(
mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_DX_JAR);
if (res != Status.OK_STATUS) {
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.FAILED;
+ mPostLoadProjects.clear();
+ }
return res;
- } else {
+ }
+
+ synchronized (mPostLoadProjects) {
+ mSdkIsLoaded = LoadStatus.LOADED;
+
// update the project that needs recompiling.
- synchronized (mPostDexProjects) {
- if (mPostDexProjects.size() > 0) {
- IJavaProject[] array = mPostDexProjects.toArray(
- new IJavaProject[mPostDexProjects.size()]);
- AndroidClasspathContainerInitializer.updateProjects(array);
- mPostDexProjects.clear();
- }
+ if (mPostLoadProjects.size() > 0) {
+ IJavaProject[] array = mPostLoadProjects.toArray(
+ new IJavaProject[mPostLoadProjects.size()]);
+ AndroidClasspathContainerInitializer.updateProjects(array);
+ mPostLoadProjects.clear();
}
}
- } finally {
- if (progress != null) {
- progress.worked(20);
+ }
+
+ // Notify resource changed listeners
+ progress.subTask("Refresh UI");
+ progress.setWorkRemaining(mResourceRefreshListener.size());
+
+ // Clone the list before iterating, to avoid Concurrent Modification
+ // exceptions
+ List<Runnable> listeners = (List<Runnable>)mResourceRefreshListener.clone();
+ for (Runnable listener : listeners) {
+ try {
+ AdtPlugin.getDisplay().syncExec(listener);
+ } catch (Exception e) {
+ AdtPlugin.log(e, "ResourceRefreshListener Failed"); //$NON-NLS-1$
+ } finally {
+ progress.worked(1);
}
}
} finally {
@@ -1112,6 +1078,252 @@ public class AdtPlugin extends AbstractUIPlugin {
return Status.OK_STATUS;
}
- }.schedule();
+ };
+ job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
+ job.schedule();
+ }
+
+ /** Returns the global android console */
+ public MessageConsole getAndroidConsole() {
+ return mAndroidConsole;
+ }
+
+ // ----- Methods for Editors -------
+
+ public void startEditors() {
+ sAndroidLogoDesc = imageDescriptorFromPlugin(AdtPlugin.PLUGIN_ID,
+ "/icons/android.png"); //$NON-NLS-1$
+ sAndroidLogo = sAndroidLogoDesc.createImage();
+
+ // get the stream to write in the android console.
+ MessageConsole androidConsole = AdtPlugin.getDefault().getAndroidConsole();
+ mAndroidConsoleStream = androidConsole.newMessageStream();
+
+ mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+ mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
+
+ // because this can be run, in some cases, by a non ui thread, and beccause
+ // changing the console properties update the ui, we need to make this change
+ // in the ui thread.
+ getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ mAndroidConsoleErrorStream.setColor(mRed);
+ }
+ });
+
+ // Add a resource listener to handle compiled resources.
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ mResourceMonitor = ResourceMonitor.startMonitoring(ws);
+
+ if (mResourceMonitor != null) {
+ try {
+ setupDefaultEditor(mResourceMonitor);
+ ResourceManager.setup(mResourceMonitor);
+ } catch (Throwable t) {
+ log(t, "ResourceManager.setup failed"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
+ * method saves this plug-in's preference and dialog stores and shuts down
+ * its image registry (if they are in use). Subclasses may extend this
+ * method, but must send super <b>last</b>. A try-finally statement should
+ * be used where necessary to ensure that <code>super.shutdown()</code> is
+ * always done.
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stopEditors() {
+ sAndroidLogo.dispose();
+
+ IconFactory.getInstance().Dispose();
+
+ // Remove the resource listener that handles compiled resources.
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ ResourceMonitor.stopMonitoring(ws);
+
+ mRed.dispose();
+ }
+
+ /**
+ * Returns an Image for the small Android logo.
+ *
+ * Callers should not dispose it.
+ */
+ public static Image getAndroidLogo() {
+ return sAndroidLogo;
+ }
+
+ /**
+ * Returns an {@link ImageDescriptor} for the small Android logo.
+ *
+ * Callers should not dispose it.
+ */
+ public static ImageDescriptor getAndroidLogoDesc() {
+ return sAndroidLogoDesc;
+ }
+
+ /**
+ * Returns the ResourceMonitor object.
+ */
+ public ResourceMonitor getResourceMonitor() {
+ return mResourceMonitor;
+ }
+
+ /**
+ * Sets up the editor to register default editors for resource files when needed.
+ *
+ * This is called by the {@link AdtPlugin} during initialization.
+ *
+ * @param monitor The main Resource Monitor object.
+ */
+ public void setupDefaultEditor(ResourceMonitor monitor) {
+ monitor.addFileListener(new IFileListener() {
+
+ private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * Sent when a file changed.
+ * @param file The file that changed.
+ * @param markerDeltas The marker deltas for the file.
+ * @param kind The change kind. This is equivalent to
+ * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
+ *
+ * @see IFileListener#fileChanged
+ */
+ public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
+ if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
+ // The resources files must have a file path similar to
+ // project/res/.../*.xml
+ // There is no support for sub folders, so the segment count must be 4
+ if (file.getFullPath().segmentCount() == 4) {
+ // check if we are inside the res folder.
+ String segment = file.getFullPath().segment(1);
+ if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
+ // we are inside a res/ folder, get the actual ResourceFolder
+ ProjectResources resources = ResourceManager.getInstance().
+ getProjectResources(file.getProject());
+
+ // This happens when importing old Android projects in Eclipse
+ // that lack the container (probably because resources fail to build
+ // properly.)
+ if (resources == null) {
+ log(IStatus.INFO,
+ "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
+ file.getFullPath().toOSString(),
+ file.getProject().getName());
+ return;
+ }
+
+ ResourceFolder resFolder = resources.getResourceFolder(
+ (IFolder)file.getParent());
+
+ if (resFolder != null) {
+ if (kind == IResourceDelta.ADDED) {
+ resourceAdded(file, resFolder.getType());
+ } else if (kind == IResourceDelta.CHANGED) {
+ resourceChanged(file, resFolder.getType());
+ }
+ } else {
+ // if the res folder is null, this means the name is invalid,
+ // in this case we remove whatever android editors that was set
+ // as the default editor.
+ IEditorDescriptor desc = IDE.getDefaultEditor(file);
+ String editorId = desc.getId();
+ if (editorId.startsWith(AndroidConstants.EDITORS_NAMESPACE)) {
+ // reset the default editor.
+ IDE.setDefaultEditor(file, null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void resourceAdded(IFile file, ResourceFolderType type) {
+ // set the default editor based on the type.
+ if (type == ResourceFolderType.LAYOUT) {
+ IDE.setDefaultEditor(file, LayoutEditor.ID);
+ } else if (type == ResourceFolderType.DRAWABLE
+ || type == ResourceFolderType.VALUES) {
+ IDE.setDefaultEditor(file, ResourcesEditor.ID);
+ } else if (type == ResourceFolderType.MENU) {
+ IDE.setDefaultEditor(file, MenuEditor.ID);
+ } else if (type == ResourceFolderType.XML) {
+ if (XmlEditor.canHandleFile(file)) {
+ IDE.setDefaultEditor(file, XmlEditor.ID);
+ } else {
+ // set a property to determine later if the XML can be handled
+ QualifiedName qname = new QualifiedName(
+ AdtPlugin.PLUGIN_ID,
+ UNKNOWN_EDITOR);
+ try {
+ file.setPersistentProperty(qname, "1");
+ } catch (CoreException e) {
+ // pass
+ }
+ }
+ }
+ }
+
+ private void resourceChanged(IFile file, ResourceFolderType type) {
+ if (type == ResourceFolderType.XML) {
+ IEditorDescriptor ed = IDE.getDefaultEditor(file);
+ if (ed == null || ed.getId() != XmlEditor.ID) {
+ QualifiedName qname = new QualifiedName(
+ AdtPlugin.PLUGIN_ID,
+ UNKNOWN_EDITOR);
+ String prop = null;
+ try {
+ prop = file.getPersistentProperty(qname);
+ } catch (CoreException e) {
+ // pass
+ }
+ if (prop != null && XmlEditor.canHandleFile(file)) {
+ try {
+ // remove the property & set editor
+ file.setPersistentProperty(qname, null);
+ IWorkbenchPage page = PlatformUI.getWorkbench().
+ getActiveWorkbenchWindow().getActivePage();
+
+ IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
+ if (oldEditor != null &&
+ AdtPlugin.displayPrompt("Android XML Editor",
+ String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
+ file.getFullPath()))) {
+ IDE.setDefaultEditor(file, XmlEditor.ID);
+ IEditorPart newEditor = page.openEditor(
+ new FileEditorInput(file),
+ XmlEditor.ID,
+ true, /* activate */
+ IWorkbenchPage.MATCH_NONE);
+
+ if (newEditor != null) {
+ page.closeEditor(oldEditor, true /* save */);
+ }
+ }
+ } catch (CoreException e) {
+ // setPersistentProperty or page.openEditor may have failed
+ }
+ }
+ }
+ }
+ }
+
+ }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
+ }
+
+ public void addResourceChangedListener(Runnable resourceRefreshListener) {
+ mResourceRefreshListener.add(resourceRefreshListener);
+ }
+
+ public void removeResourceChangedListener(Runnable resourceRefreshListener) {
+ mResourceRefreshListener.remove(resourceRefreshListener);
+ }
+
+ public static synchronized OutputStream getErrorStream() {
+ return sPlugin.mAndroidConsoleErrorStream;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
index bac940a..6d85af3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.adt;
-import com.android.ddmlib.Device;
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.SdkConstants;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
@@ -42,19 +41,6 @@ import java.util.regex.Pattern;
*
*/
final class VersionCheck {
-
- /** Pattern to get the SDK build incremental version from the
- * <code>$SDK/tools/lib/build.prop file</code>. */
- private final static Pattern sBuildVersionPattern = Pattern.compile(
- "^" + Device.PROP_BUILD_VERSION + "=(.+)$"); //$NON-NLS-1$
-
- /**
- * Pattern to parse release type SDK version number. This parses the content read with
- * <code>sBuildIdPattern</code>.
- */
- private final static Pattern sSdkVersionPattern = Pattern.compile(
- "^(\\d+)\\.(\\d+)_r(\\d+)$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
-
/**
* Pattern to get the minimum plugin version supported by the SDK. This is read from
* the file <code>$SDK/tools/lib/plugin.prop</code>.
@@ -69,58 +55,7 @@ final class VersionCheck {
*/
public static boolean checkVersion(String osSdkPath, CheckSdkErrorHandler errorHandler) {
AdtPlugin plugin = AdtPlugin.getDefault();
- String osLibs = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
- /*
- * All plugins should work with all SDKs. Newer SDKs may require a newer plugin
- * but this is handled below.
- * Still, we need to grab the SDK version from this file. This is used
- * to compare to running emulator/device when launching run/debug sessions.
- */
- try {
- FileReader reader = new FileReader(osLibs + AndroidConstants.FN_BUILD_PROP);
- BufferedReader bReader = new BufferedReader(reader);
- String line;
- while ((line = bReader.readLine()) != null) {
- Matcher m = sBuildVersionPattern.matcher(line);
- if (m.matches()) {
- plugin.mSdkApiVersion = m.group(1).trim();
-
- /*
- * No checks on the version at the moment.
- */
- /*
- if (plugin.mSdkBuildVersion != null) {
- // attempt to get version number from the build id
- m = sSdkVersionPattern.matcher(plugin.mSdkBuildVersion);
- if (m.matches()) {
- // get the platform version number
- int platformMajor = Integer.parseInt(m.group(1));
- int platformMinor = Integer.parseInt(m.group(2));
- @SuppressWarnings("unused") //$NON-NLS-1$
- int sdkRelease = Integer.parseInt(m.group(3));
-
- if (platformMajor != 0 || platformMinor != 9) {
- return errorHandler.handleError(String.format(
- "This version of ADT requires the Android SDK version 0.9\n\nCurrent version is %1$s.\n\nPlease update your SDK to the latest version.",
- plugin.mSdkBuildVersion));
- }
- } else {
- // unknown version format.
- AdtPlugin.printErrorToConsole(
- (Object)String.format(Messages.VersionCheck_Unable_To_Parse_Version_s,
- plugin.mSdkBuildVersion));
- }
- }
- */
- break;
- }
- }
- } catch (FileNotFoundException e) {
- // the build id will be null, and this is handled by the builders.
- } catch (IOException e) {
- // the build id will be null, and this is handled by the builders.
- }
+ String osLibs = osSdkPath + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
// get the plugin property file, and grab the minimum plugin version required
// to work with the sdk
@@ -128,7 +63,7 @@ final class VersionCheck {
int minMinorVersion = -1;
int minMicroVersion = -1;
try {
- FileReader reader = new FileReader(osLibs + AndroidConstants.FN_PLUGIN_PROP);
+ FileReader reader = new FileReader(osLibs + SdkConstants.FN_PLUGIN_PROP);
BufferedReader bReader = new BufferedReader(reader);
String line;
while ((line = bReader.readLine()) != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
index 0b1b647..4d16120 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
@@ -19,6 +19,8 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.jarutils.DebugKeyProvider;
@@ -28,6 +30,7 @@ import com.android.jarutils.DebugKeyProvider.IKeyGenOutput;
import com.android.jarutils.DebugKeyProvider.KeytoolException;
import com.android.jarutils.SignedJarBuilder.IZipEntryFilter;
import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -44,6 +47,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -296,6 +300,15 @@ public class ApkBuilder extends BaseBuilder {
saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage);
+ // At this point, we can abort the build if we have to, as we have computed
+ // our resource delta and stored the result.
+
+ // check if we have finished loading the SDK.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+ // we exit silently
+ return referencedProjects;
+ }
+
// Now check the compiler compliance level, not displaying the error
// message since this is not the first builder.
if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -502,7 +515,8 @@ public class ApkBuilder extends BaseBuilder {
commandArray.add(osAssetsPath);
}
commandArray.add("-I"); //$NON-NLS-1$
- commandArray.add(AdtPlugin.getOsAbsoluteFramework());
+ commandArray.add(
+ Sdk.getCurrent().getTarget(project).getPath(IAndroidTarget.ANDROID_JAR));
commandArray.add("-F"); //$NON-NLS-1$
commandArray.add(osOutFilePath);
@@ -584,16 +598,9 @@ public class ApkBuilder extends BaseBuilder {
DexWrapper wrapper = DexWrapper.getWrapper();
if (wrapper == null) {
- if (DexWrapper.getStatus() == DexWrapper.LoadStatus.FAILED) {
+ if (DexWrapper.getStatus() == LoadStatus.FAILED) {
throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
Messages.ApkBuilder_UnableBuild_Dex_Not_loaded));
- } else {
- // means we haven't loaded the dex jar yet.
- // We set the project to be recompiled after dex is loaded.
- AdtPlugin.getDefault().addPostDexProject(javaProject);
-
- // and we exit silently
- return false;
}
}
@@ -677,7 +684,7 @@ public class ApkBuilder extends BaseBuilder {
}
// TODO: get the store type from somewhere else.
- DebugKeyProvider provider = new DebugKeyProvider(null /* storeType */,
+ DebugKeyProvider provider = new DebugKeyProvider(osKeyPath, null /* storeType */,
new IKeyGenOutput() {
public void err(String message) {
AdtPlugin.printErrorToConsole(javaProject.getProject(),
@@ -747,9 +754,18 @@ public class ApkBuilder extends BaseBuilder {
}
}
+ // now write the native libraries.
+ // First look if the lib folder is there.
+ IResource libFolder = javaProject.getProject().findMember(
+ AndroidConstants.FD_NATIVE_LIBS);
+ if (libFolder != null && libFolder.exists() &&
+ libFolder.getType() == IResource.FOLDER) {
+ // look inside and put .so in lib/* by keeping the relative folder path.
+ writeNativeLibraries(libFolder.getFullPath().segmentCount(), builder, libFolder);
+ }
+
// close the jar file and write the manifest and sign it.
builder.close();
-
} catch (GeneralSecurityException e1) {
// mark project and return
String msg = String.format(Messages.Final_Archive_Error_s, e1.getMessage());
@@ -784,6 +800,12 @@ public class ApkBuilder extends BaseBuilder {
// and also output it in the console
AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+ } catch (CoreException e) {
+ // mark project and return
+ String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage());
+ AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+ markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+ return false;
} finally {
if (fos != null) {
try {
@@ -798,6 +820,48 @@ public class ApkBuilder extends BaseBuilder {
}
/**
+ * Writes native libraries into a {@link SignedJarBuilder}.
+ * <p/>This recursively go through folder and writes .so files.
+ * The path in the archive is based on the root folder containing the libraries in the project.
+ * Its segment count is passed to the method to compute the resources path relative to the root
+ * folder.
+ * Native libraries in the archive must be in a "lib" folder. Everything in the project native
+ * lib folder directly goes in this "lib" folder in the archive.
+ *
+ *
+ * @param rooSegmentCount The number of segment of the path of the folder containing the
+ * libraries. This is used to compute the path in the archive.
+ * @param jarBuilder the {@link SignedJarBuilder} used to create the archive.
+ * @param resource the IResource to write.
+ * @throws CoreException
+ * @throws IOException
+ */
+ private void writeNativeLibraries(int rootSegmentCount, SignedJarBuilder jarBuilder,
+ IResource resource) throws CoreException, IOException {
+ if (resource.getType() == IResource.FILE) {
+ IPath path = resource.getFullPath();
+
+ // check the extension.
+ if (path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+ // remove the first segment to build the path inside the archive.
+ path = path.removeFirstSegments(rootSegmentCount);
+
+ // add it to the archive.
+ IPath apkPath = new Path(AndroidConstants.FD_APK_NATIVE_LIBS);
+ apkPath = apkPath.append(path);
+
+ // writes the file in the apk.
+ jarBuilder.writeFile(resource.getLocation().toFile(), apkPath.toString());
+ }
+ } else if (resource.getType() == IResource.FOLDER) {
+ IResource[] members = ((IFolder)resource).members();
+ for (IResource member : members) {
+ writeNativeLibraries(rootSegmentCount, jarBuilder, member);
+ }
+ }
+ }
+
+ /**
* Writes the standard resources of a project and its referenced projects
* into a {@link SignedJarBuilder}.
* Standard resources are non java/aidl files placed in the java package folders.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
index fb60fdb..47ef626 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
@@ -42,6 +42,7 @@ import java.util.ArrayList;
* <li>Any change to the classes.dex inside the output folder</li>
* <li>Any change to the packaged resources file inside the output folder</li>
* <li>Any change to a non java/aidl file inside the source folders</li>
+ * <li>Any change to .so file inside the lib (native library) folder</li>
* </ul>
*/
public class ApkDeltaVisitor extends BaseDeltaVisitor
@@ -79,6 +80,8 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
private IPath mResPath;
+ private IPath mLibFolder;
+
/**
* Builds the object with a specified output folder.
* @param builder the xml builder using this object to visit the
@@ -104,6 +107,11 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
if (resFolder != null) {
mResPath = resFolder.getFullPath();
}
+
+ IResource libFolder = builder.getProject().findMember(AndroidConstants.FD_NATIVE_LIBS);
+ if (libFolder != null) {
+ mLibFolder = libFolder.getFullPath();
+ }
}
public boolean getConvertToDex() {
@@ -161,6 +169,7 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
// check the other folders.
if (mOutputPath != null && mOutputPath.isPrefixOf(path)) {
+ // a resource changed inside the output folder.
if (type == IResource.FILE) {
// just check this is a .class file. Any modification will
// trigger a change in the classes.dex file
@@ -217,6 +226,17 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor
mPackageResources = true;
mMakeFinalPackage = true;
return false;
+ } else if (mLibFolder != null && mLibFolder.isPrefixOf(path)) {
+ // inside the native library folder. Test if the changed resource is a .so file.
+ if (type == IResource.FILE &&
+ path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+ mMakeFinalPackage = true;
+ return false; // return false for file.
+ }
+
+ // for folders, return true only if we don't already know we have to make the
+ // final package.
+ return mMakeFinalPackage == false;
} else {
// we are in a folder that is neither the resource folders, nor the output.
// check against all the source folders, unless we already know we need to do
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
index f79be3d..f94bdc7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
@@ -806,12 +806,6 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
// get the IPath
IPath path = e.getPath();
- // get the file name. if it's the framework jar, we ignore that file.
- // since we now use classpath container, this is here for legacy purpose only.
- if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
- continue;
- }
-
// check the name ends with .jar
if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
boolean local = false;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
index 9ba4026..cba8ad7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
@@ -47,9 +48,6 @@ public final class DexWrapper {
private static DexWrapper sWrapper;
- /** Status for the Loading of the dex jar file */
- public enum LoadStatus { LOADING, LOADED, FAILED }
-
private static LoadStatus sLoadStatus = LoadStatus.LOADING;
private Method mRunMethod;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
index 850a79a..1a4aa8c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
@@ -18,14 +18,16 @@ package com.android.ide.eclipse.adt.build;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor;
import com.android.ide.eclipse.adt.project.FixLaunchConfig;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -44,7 +46,6 @@ import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.ui.ide.IDE;
import java.io.IOException;
import java.util.ArrayList;
@@ -130,7 +131,6 @@ public class PreCompilerBuilder extends BaseBuilder {
mSource);
try {
mNewFile.setDerived(true);
- IDE.setDefaultEditor(mNewFile, ReadOnlyJavaEditor.ID);
} catch (CoreException e) {
// This really shouldn't happen since we check that the resource exist.
// Worst case scenario, the resource isn't marked as derived.
@@ -266,8 +266,14 @@ public class PreCompilerBuilder extends BaseBuilder {
// record the state
mCompileResources |= dv.getCompileResources();
- mergeAidlFileModifications(dv.getAidlToCompile(),
- dv.getAidlToRemove());
+
+ // handle aidl modification
+ if (dv.getFullAidlRecompilation()) {
+ buildAidlCompilationList(project, sourceList);
+ } else {
+ mergeAidlFileModifications(dv.getAidlToCompile(),
+ dv.getAidlToRemove());
+ }
// if there was some XML errors, we just return w/o doing
// anything since we've put some markers in the files anyway.
@@ -290,6 +296,12 @@ public class PreCompilerBuilder extends BaseBuilder {
// At this point we have stored what needs to be build, so we can
// do some high level test and abort if needed.
+ // check if we have finished loading the SDK.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+ // we exit silently
+ return null;
+ }
+
// check the compiler compliance level, not displaying the error message
// since this is not the first builder.
if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -302,13 +314,19 @@ public class PreCompilerBuilder extends BaseBuilder {
// Check that the SDK directory has been setup.
String osSdkFolder = AdtPlugin.getOsSdkFolder();
- if (osSdkFolder.length() == 0) {
+ if (osSdkFolder == null || osSdkFolder.length() == 0) {
AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
Messages.No_SDK_Setup_Error);
markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
IMarker.SEVERITY_ERROR);
return null;
}
+
+ IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
+ if (projectTarget == null) {
+ // no target. error has been output by the container initializer: exit silently.
+ return null;
+ }
// get the manifest file
IFile manifest = AndroidManifestHelper.getManifest(project);
@@ -448,7 +466,7 @@ public class PreCompilerBuilder extends BaseBuilder {
array.add("-S"); //$NON-NLS-1$
array.add(osResPath);
array.add("-I"); //$NON-NLS-1$
- array.add(AdtPlugin.getOsAbsoluteFramework());
+ array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
StringBuilder sb = new StringBuilder();
@@ -563,6 +581,8 @@ public class PreCompilerBuilder extends BaseBuilder {
deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
mManifestPackageSourceFolder, mManifestPackage);
}
+
+ // FIXME: delete all java generated from aidl.
}
@Override
@@ -736,12 +756,14 @@ public class PreCompilerBuilder extends BaseBuilder {
if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
return false;
}
+
// create the command line
String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)];
int index = 0;
+ int aidlIndex;
command[index++] = AdtPlugin.getOsAbsoluteAidl();
- command[index++] = "-p" + AdtPlugin.getOsAbsoluteFrameworkAidl(); //$NON-NLS-1$
+ command[aidlIndex = index++] = "-p"; //$NON-NLS-1$
if (folderAidlPath != null) {
command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$
}
@@ -813,6 +835,8 @@ public class PreCompilerBuilder extends BaseBuilder {
prepareFileForExternalModification(javaFile);
// finish to set the command line.
+ command[aidlIndex] = "-p" + Sdk.getCurrent().getTarget(aidlFile.getProject()).getPath(
+ IAndroidTarget.ANDROID_AIDL); //$NON-NLS-1$
command[index] = osPath;
command[index + 1] = osJavaPath;
@@ -922,7 +946,8 @@ public class PreCompilerBuilder extends BaseBuilder {
}
/**
- * Goes through the buildpath and fills the list of aidl files to compile.
+ * Goes through the build paths and fills the list of aidl files to compile
+ * ({@link #mAidlToCompile}).
* @param project The project.
* @param buildPaths The list of build paths.
*/
@@ -977,7 +1002,7 @@ public class PreCompilerBuilder extends BaseBuilder {
scanContainerForAidl((IFolder)r);
break;
default:
- // this would mean it's a project or the workspaceroot
+ // this would mean it's a project or the workspace root
// which is unlikely to happen. we do nothing
break;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
index 9c3bc5c..33d5fa6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
@@ -42,6 +42,7 @@ import java.util.ArrayList;
class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
IResourceDeltaVisitor {
+ // Result fields.
/**
* Compile flag. This is set to true if one of the changed/added/removed
* file is a resource file. Upon visiting all the delta resources, if
@@ -50,6 +51,22 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
*/
private boolean mCompileResources = false;
+ /** List of .aidl files found that are modified or new. */
+ private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+
+ /** List of .aidl files that have been removed. */
+ private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+
+ /** Aidl forced recompilation flag. This is set to true if project.aidl is modified. */
+ private boolean mFullAidlCompilation = false;
+
+ /** Manifest check/parsing flag. */
+ private boolean mCheckedManifestXml = false;
+
+ /** Application Pacakge, gathered from the parsing of the manifest */
+ private String mJavaPackage = null;
+
+ // Internal usage fields.
/**
* In Resource folder flag. This allows us to know if we're in the
* resource folder.
@@ -65,14 +82,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
/** List of source folders. */
private ArrayList<IPath> mSourceFolders;
- /** List of .aidl files found that are modified or new. */
- private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
-
- /** List of .aidl files that have been removed. */
- private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
-
- private boolean mCheckedManifestXml = false;
- private String mJavaPackage = null;
public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
super(builder);
@@ -90,6 +99,10 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
public ArrayList<IFile> getAidlToRemove() {
return mAidlToRemove;
}
+
+ public boolean getFullAidlRecompilation() {
+ return mFullAidlCompilation;
+ }
/**
* Returns whether the manifest file was parsed/checked for error during the resource delta
@@ -100,7 +113,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
}
/**
- * Returns the manifest package if the manifest was checked.
+ * Returns the manifest package if the manifest was checked/parsed.
* <p/>
* This can return null in two cases:
* <ul>
@@ -169,11 +182,14 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// we don't want to go to the children, not like they are
// any for this resource anyway.
return false;
+ } else if (AndroidConstants.FN_PROJECT_AIDL.equalsIgnoreCase(segments[1])) {
+ // need to force recompilation of all the aidl files
+ mFullAidlCompilation = true;
}
}
// at this point we can either be in the source folder or in the
- // resource foler or in a different folder that contains a source
+ // resource folder or in a different folder that contains a source
// folder.
// This is due to not all source folder being src/. Some could be
// something/somethingelse/src/
@@ -227,7 +243,8 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, true);
}
- // we add it anyway so that we can try to compile it every time.
+ // we add it anyway so that we can try to compile it at every compilation
+ // until the conflict is fixed.
mAidlToCompile.add(file);
} else {
@@ -245,6 +262,8 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
boolean outputMessage = false;
+ // Special case of R.java/Manifest.java.
+ // FIXME: This does not check the package. Any modification of R.java/Manifest.java in another project will trigger a new recompilation of the resources.
if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
// if it was removed, there's a possibility that it was removed due to a
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
index 1de1438..1219aac 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
@@ -62,13 +62,10 @@ public class ResourceManagerBuilder extends IncrementalProjectBuilder {
switch (res) {
case ProjectHelper.COMPILER_COMPLIANCE_LEVEL:
errorMessage = Messages.Requires_Compiler_Compliance_5;
- return null;
case ProjectHelper.COMPILER_COMPLIANCE_SOURCE:
errorMessage = Messages.Requires_Source_Compatibility_5;
- return null;
case ProjectHelper.COMPILER_COMPLIANCE_CODEGEN_TARGET:
errorMessage = Messages.Requires_Class_Compatibility_5;
- return null;
}
if (errorMessage != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
index 10be077..48ec7c3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
@@ -30,9 +30,9 @@ import com.android.ddmlib.SyncService.SyncResult;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -102,6 +102,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/** Debuggable attribute of the manifest file. */
Boolean mDebuggable = null;
+ /** Required ApiVersionNumber by the app. 0 means no requirements */
+ int mRequiredApiVersionNumber = 0;
+
InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
/**
@@ -126,8 +129,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/** Basic constructor with activity and package info. */
public DelayedLaunchInfo(IProject project, String packageName, String activity,
- IFile pack, Boolean debuggable, int launchAction, AndroidLaunch launch,
- IProgressMonitor monitor) {
+ IFile pack, Boolean debuggable, int requiredApiVersionNumber, int launchAction,
+ AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
mActivity = activity;
@@ -136,6 +139,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
mLaunch = launch;
mMonitor = monitor;
mDebuggable = debuggable;
+ mRequiredApiVersionNumber = requiredApiVersionNumber;
}
}
@@ -256,13 +260,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
try {
mSkin = config.getAttribute(LaunchConfigDelegate.ATTR_SKIN, mSkin);
if (mSkin == null) {
- mSkin = SkinRepository.getInstance().checkSkin(
- LaunchConfigDelegate.DEFAULT_SKIN);
- } else {
- mSkin = SkinRepository.getInstance().checkSkin(mSkin);
+ mSkin = SdkConstants.SKIN_DEFAULT;
}
} catch (CoreException e) {
- mSkin = SkinRepository.getInstance().checkSkin(LaunchConfigDelegate.DEFAULT_SKIN);
+ mSkin = SdkConstants.SKIN_DEFAULT;
}
int index = LaunchConfigDelegate.DEFAULT_SPEED;
@@ -539,7 +540,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
LaunchConfigDelegate.DEFAULT_DELAY);
// default skin
- wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, LaunchConfigDelegate.DEFAULT_SKIN);
+ wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, SdkConstants.SKIN_DEFAULT);
// default wipe data mode
wc.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
@@ -599,13 +600,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* defined by <code>ILaunchManager</code> - <code>RUN_MODE</code> or
* <code>DEBUG_MODE</code>.
* @param apk the resource to the apk to launch.
- * @param debuggable
+ * @param debuggable the debuggable value of the app, or null if not set.
+ * @param requiredApiVersionNumber the api version required by the app, or -1 if none.
* @param activity the class to provide to am to launch
* @param config the launch configuration
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
- String packageName, Boolean debuggable, String activity,
+ String packageName, Boolean debuggable, int requiredApiVersionNumber, String activity,
final AndroidLaunchConfiguration config, final AndroidLaunch launch,
IProgressMonitor monitor) {
@@ -619,7 +621,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
- activity, apk, debuggable, config.mLaunchAction, launch, monitor);
+ activity, apk, debuggable, requiredApiVersionNumber, config.mLaunchAction,
+ launch, monitor);
// set the debug mode
launchInfo.mDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);
@@ -711,6 +714,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// stop the launch and return
mWaitingForEmulatorLaunches.remove(launchInfo);
+ AdtPlugin.printErrorToConsole(project, "Launch canceled!");
launch.stopLaunch();
return;
}
@@ -761,31 +765,63 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
}
- private void checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
+ /**
+ * Checks the build information, and returns whether the launch should continue.
+ * <p/>The value tested are:
+ * <ul>
+ * <li>Minimum API version requested by the application. If the target device does not match,
+ * the launch is canceled.</li>
+ * <li>Debuggable attribute of the application and whether or not the device requires it. If
+ * the device requires it and it is not set in the manifest, the launch will be forced to
+ * "release" mode instead of "debug"</li>
+ * <ul>
+ * @param launchInfo
+ * @param device
+ * @return
+ */
+ private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
if (device != null) {
- // get the SDK build
- String sdkBuild = AdtPlugin.getSdkApiVersion();
-
- // can only complain if the sdkBuild is known
- if (sdkBuild != null) {
-
- String deviceVersion = device.getProperty(Device.PROP_BUILD_VERSION);
+ // check the app required API level versus the target device API level
+
+ String deviceApiVersionName = device.getProperty(Device.PROP_BUILD_VERSION);
+ String value = device.getProperty(Device.PROP_BUILD_VERSION_NUMBER);
+ int deviceApiVersionNumber = 0;
+ try {
+ deviceApiVersionNumber = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ // pass, we'll keep the deviceVersionNumber value at 0.
+ }
+
+ if (launchInfo.mRequiredApiVersionNumber == 0) {
+ // warn the API level requirement is not set.
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "WARNING: Application does not specify an API level requirement!");
- if (deviceVersion == null) {
- AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown device API version!");
+ // and display the target device API level (if known)
+ if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "WARNING: Unknown device API version!");
} else {
- if (sdkBuild.equals(deviceVersion) == false) {
- // TODO do a proper check, including testing the content of the uses-sdk string in the manifest to detect real incompatibility.
- String msg = String.format(
- "WARNING: Device API version (%1$s) does not match SDK API version (%2$s)",
- deviceVersion, sdkBuild);
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
- }
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(
+ "Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
+ deviceApiVersionName));
+ }
+ } else { // app requires a specific API level
+ if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+ AdtPlugin.printToConsole(launchInfo.mProject,
+ "WARNING: Unknown device API version!");
+ } else if (deviceApiVersionNumber < launchInfo.mRequiredApiVersionNumber) {
+ String msg = String.format(
+ "ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
+ launchInfo.mRequiredApiVersionNumber, deviceApiVersionNumber,
+ deviceApiVersionName);
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+
+ // abort the launch
+ return false;
}
- } else {
- AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown SDK API version!");
}
-
+
// now checks that the device/app can be debugged (if needed)
if (device.isEmulator() == false && launchInfo.mDebugMode) {
String debuggableDevice = device.getProperty(Device.PROP_DEBUGGABLE);
@@ -818,6 +854,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
}
}
+
+ return true;
}
/**
@@ -829,10 +867,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @return true if succeed
*/
private boolean simpleLaunch(DelayedLaunchInfo launchInfo, Device device) {
- checkBuildInfo(launchInfo, device);
+ // API level check
+ if (checkBuildInfo(launchInfo, device) == false) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
+ launchInfo.mLaunch.stopLaunch();
+ return false;
+ }
// sync the app
if (syncApp(launchInfo, device) == false) {
+ AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
launchInfo.mLaunch.stopLaunch();
return false;
}
@@ -1127,6 +1171,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
} catch (IOException e) {
// something went wrong trying to launch the app.
// lets stop the Launch
+ AdtPlugin.printErrorToConsole(info.mProject,
+ String.format("Launch error: %s", e.getMessage()));
info.mLaunch.stopLaunch();
// and remove it from the list of app waiting for debuggers
@@ -1139,25 +1185,20 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
private boolean launchEmulator(AndroidLaunchConfiguration config) {
// split the custom command line in segments
- String[] segs;
+ ArrayList<String> customArgs = new ArrayList<String>();
boolean has_wipe_data = false;
if (config.mEmulatorCommandLine != null && config.mEmulatorCommandLine.length() > 0) {
- segs = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
+ String[] segments = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
// we need to remove the empty strings
- ArrayList<String> array = new ArrayList<String>();
- for (String s : segs) {
+ for (String s : segments) {
if (s.length() > 0) {
- array.add(s);
+ customArgs.add(s);
if (!has_wipe_data && s.equals(FLAG_WIPE_DATA)) {
has_wipe_data = true;
}
}
}
-
- segs = array.toArray(new String[array.size()]);
- } else {
- segs = new String[0];
}
boolean needs_wipe_data = config.mWipeData && !has_wipe_data;
@@ -1167,30 +1208,38 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
}
- boolean needs_no_boot_anim = config.mNoBootAnim;
+ // build the command line based on the available parameters.
+ ArrayList<String> list = new ArrayList<String>();
+
+ list.add(AdtPlugin.getOsAbsoluteEmulator());
+ if (config.mSkin != null) {
+ list.add(FLAG_SKIN);
+ list.add(config.mSkin);
+ }
- // get the command line
- String[] command = new String[7 + segs.length +
- (needs_wipe_data ? 1 : 0) +
- (needs_no_boot_anim ? 1 : 0)];
- int index = 0;
- command[index++] = AdtPlugin.getOsAbsoluteEmulator();
- command[index++] = FLAG_SKIN; //$NON-NLS-1$
- command[index++] = config.mSkin;
- command[index++] = FLAG_NETSPEED; //$NON-NLS-1$
- command[index++] = config.mNetworkSpeed;
- command[index++] = FLAG_NETDELAY; //$NON-NLS-1$
- command[index++] = config.mNetworkDelay;
- if (needs_wipe_data) {
- command[index++] = FLAG_WIPE_DATA;
+ if (config.mNetworkSpeed != null) {
+ list.add(FLAG_NETSPEED);
+ list.add(config.mNetworkSpeed);
}
- if (needs_no_boot_anim) {
- command[index++] = FLAG_NO_BOOT_ANIM;
+
+ if (config.mNetworkDelay != null) {
+ list.add(FLAG_NETDELAY);
+ list.add(config.mNetworkDelay);
+ }
+
+ if (needs_wipe_data) {
+ list.add(FLAG_WIPE_DATA);
}
- for (String s : segs) {
- command[index++] = s;
+
+ if (config.mNoBootAnim) {
+ list.add(FLAG_NO_BOOT_ANIM);
}
+ list.addAll(customArgs);
+
+ // convert the list into an array for the call to exec.
+ String[] command = list.toArray(new String[list.size()]);
+
// launch the emulator
try {
Process process = Runtime.getRuntime().exec(command);
@@ -1278,12 +1327,11 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/**
* Launch a new thread that connects a remote debugger on the specified port.
* @param debugPort The port to connect the debugger to
- * @param launch The associated AndroidLaunch object.
+ * @param androidLaunch The associated AndroidLaunch object.
* @param monitor A Progress monitor
* @see connectRemoveDebugger()
*/
- public static void launchRemoteDebugger(final ILaunchConfiguration config,
- final int debugPort, final AndroidLaunch androidLaunch,
+ public static void launchRemoteDebugger( final int debugPort, final AndroidLaunch androidLaunch,
final IProgressMonitor monitor) {
new Thread("Debugger connection") { //$NON-NLS-1$
@Override
@@ -1342,13 +1390,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
synchronized (sListLock) {
// look if there's an app waiting for a device
if (mWaitingForEmulatorLaunches.size() > 0) {
- // remove first item from the list
+ // get/remove first launch item from the list
+ // FIXME: what if we have multiple launches waiting?
DelayedLaunchInfo launchInfo = mWaitingForEmulatorLaunches.get(0);
mWaitingForEmulatorLaunches.remove(0);
-
- // give it its device
+
+ // give the launch item its device for later use.
launchInfo.mDevice = device;
-
+
// and move it to the other list
mWaitingForReadyEmulatorList.add(launchInfo);
@@ -1433,12 +1482,23 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// look for application waiting for home
synchronized (sListLock) {
- boolean foundMatch = false;
for (int i = 0 ; i < mWaitingForReadyEmulatorList.size() ;) {
DelayedLaunchInfo launchInfo = mWaitingForReadyEmulatorList.get(i);
if (launchInfo.mDevice == device) {
// it's match, remove from the list
mWaitingForReadyEmulatorList.remove(i);
+
+ // We couldn't check earlier the API level of the device
+ // (it's asynchronous when the device boot, and usually
+ // deviceConnected is called before it's queried for its build info)
+ // so we check now
+ if (checkBuildInfo(launchInfo, device) == false) {
+ // device is not the proper API!
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "Launch canceled!");
+ launchInfo.mLaunch.stopLaunch();
+ return;
+ }
AdtPlugin.printToConsole(launchInfo.mProject,
String.format("HOME is up on device '%1$s'",
@@ -1448,16 +1508,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (syncApp(launchInfo, device)) {
// application package is sync'ed, lets attempt to launch it.
launchApp(launchInfo, device);
-
- // if we haven't checked the device build info, lets do it here
- if (foundMatch == false) {
- foundMatch = true;
- checkBuildInfo(launchInfo, device);
- }
} else {
// failure! Cancel and return
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ "Launch canceled!");
launchInfo.mLaunch.stopLaunch();
}
+
+ break;
} else {
i++;
}
@@ -1530,6 +1588,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
} catch (CoreException e) {
// well something went wrong.
+ AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ String.format("Launch error: %s", e.getMessage()));
// stop the launch
launchInfo.mLaunch.stopLaunch();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
index e5ccb2b..5d3e349 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
@@ -83,11 +83,6 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
/** Skin to be used to launch the emulator */
public static final String ATTR_SKIN = AdtPlugin.PLUGIN_ID + ".skin"; //$NON-NLS-1$
- /**
- * Name of the default Skin.
- */
- public static final String DEFAULT_SKIN = "HVGA"; //$NON-NLS-1$
-
public static final String ATTR_SPEED = AdtPlugin.PLUGIN_ID + ".speed"; //$NON-NLS-1$
/**
@@ -138,8 +133,7 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
// if we have a valid debug port, this means we're debugging an app
// that's already launched.
if (debugPort != INVALID_DEBUG_PORT) {
- AndroidLaunchController.launchRemoteDebugger(configuration,
- debugPort, androidLaunch, monitor);
+ AndroidLaunchController.launchRemoteDebugger(debugPort, androidLaunch, monitor);
return;
}
@@ -302,7 +296,8 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
// everything seems fine, we ask the launch controller to handle
// the rest
controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
- manifestParser.getDebuggable(), activityName, config, androidLaunch, monitor);
+ manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
+ activityName, config, androidLaunch, monitor);
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
index 1d36add..c7b340c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
@@ -18,13 +18,19 @@ package com.android.ide.eclipse.adt.debug.ui;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository.Skin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
@@ -82,6 +88,8 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
private Button mNoBootAnimButton;
+ private IAndroidTarget mTarget;
+
/**
* Returns the emulator ready speed option value.
* @param value The index of the combo selection.
@@ -169,12 +177,6 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Screen Size:");
mSkinCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);
- Skin[] skins = SkinRepository.getInstance().getSkins();
- if (skins != null) {
- for (Skin skin : skins) {
- mSkinCombo.add(skin.getDescription());
- }
- }
mSkinCombo.addSelectionListener(new SelectionAdapter() {
// called when selection changes
@Override
@@ -182,7 +184,6 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
updateLaunchConfigurationDialog();
}
});
- mSkinCombo.pack();
// network options
new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:");
@@ -287,6 +288,42 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
}
mAutoTargetButton.setSelection(value);
mManualTargetButton.setSelection(!value);
+
+ // look for the project name to get its target.
+ String projectName = "";
+ try {
+ projectName = configuration.getAttribute(
+ IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
+ } catch (CoreException ce) {
+ }
+
+ IProject project = null;
+
+ // get the list of existing Android projects from the workspace.
+ IJavaProject[] projects = BaseProjectHelper.getAndroidProjects();
+ if (projects != null) {
+ // look for the project whose name we read from the configuration.
+ for (IJavaProject p : projects) {
+ if (p.getElementName().equals(projectName)) {
+ project = p.getProject();
+ break;
+ }
+ }
+ }
+
+ mSkinCombo.removeAll();
+ if (project != null) {
+ mTarget = Sdk.getCurrent().getTarget(project);
+ if (mTarget != null) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null) {
+ for (String skin : skins) {
+ mSkinCombo.add(skin);
+ }
+ mSkinCombo.pack();
+ }
+ }
+ }
value = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
try {
@@ -307,16 +344,18 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
int index = -1;
try {
String skin = configuration.getAttribute(LaunchConfigDelegate.ATTR_SKIN, (String)null);
- if (skin != null) {
- index = getSkinIndex(skin);
+ if (skin == null) {
+ skin = SdkConstants.SKIN_DEFAULT;
}
+
+ index = getSkinIndex(skin);
} catch (CoreException e) {
- index = getSkinIndex(SkinRepository.getInstance().checkSkin(
- LaunchConfigDelegate.DEFAULT_SKIN));
+ index = getSkinIndex(SdkConstants.SKIN_DEFAULT);
}
if (index == -1) {
- mSkinCombo.clearSelection();
+ mSkinCombo.select(0);
+ updateLaunchConfigurationDialog();
} else {
mSkinCombo.select(index);
}
@@ -387,7 +426,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
LaunchConfigDelegate.DEFAULT_TARGET_MODE);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SKIN,
- LaunchConfigDelegate.DEFAULT_SKIN);
+ SdkConstants.SKIN_DEFAULT);
configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
LaunchConfigDelegate.DEFAULT_SPEED);
configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
@@ -403,11 +442,31 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {
}
private String getSkinNameByIndex(int index) {
- return SkinRepository.getInstance().getSkinNameByIndex(index);
+ if (mTarget != null && index > 0) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null && index < skins.length) {
+ return skins[index];
+ }
+ }
+
+ return null;
}
private int getSkinIndex(String name) {
- return SkinRepository.getInstance().getSkinIndex(name);
+ if (mTarget != null) {
+ String[] skins = mTarget.getSkins();
+ if (skins != null) {
+ int index = 0;
+ for (String skin : skins) {
+ if (skin.equalsIgnoreCase(name)) {
+ return index;
+ }
+ index++;
+ }
+ }
+ }
+
+ return -1;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
deleted file mode 100644
index a813026..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007 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.debug.ui;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import java.io.File;
-import java.util.ArrayList;
-
-/**
- * Repository for the emulator skins. This class is responsible for parsing the skin folder.
- */
-public class SkinRepository {
-
- private final static SkinRepository sInstance = new SkinRepository();
-
- private Skin[] mSkins;
-
- public static class Skin {
-
- String mName;
-
- public Skin(String name) {
- mName = name;
- }
-
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the human readable description of the skin.
- */
- public String getDescription() {
- // TODO: parse the skin and output the description.
- return mName;
- }
- }
-
- /**
- * Returns the singleton instance.
- */
- public static SkinRepository getInstance() {
- return sInstance;
- }
-
- /**
- * Parse the skin folder and build the skin list.
- * @param osPath The path of the skin folder.
- */
- public void parseFolder(String osPath) {
- File skinFolder = new File(osPath);
-
- if (skinFolder.isDirectory()) {
- ArrayList<Skin> skinList = new ArrayList<Skin>();
-
- File[] files = skinFolder.listFiles();
-
- for (File skin : files) {
- if (skin.isDirectory()) {
- // check for layout file
- File layout = new File(skin.getPath() + File.separator
- + AndroidConstants.FN_LAYOUT);
-
- if (layout.isFile()) {
- // for now we don't parse the content of the layout and
- // simply add the directory to the list.
- skinList.add(new Skin(skin.getName()));
- }
- }
- }
-
- mSkins = skinList.toArray(new Skin[skinList.size()]);
- } else {
- mSkins = new Skin[0];
- }
- }
-
- public Skin[] getSkins() {
- return mSkins;
- }
-
- /**
- * Returns a valid skin folder name. If <code>skin</code> is valid, then it is returned,
- * otherwise the first valid skin name is returned.
- * @param skin the Skin name to check
- * @return a valid skin name or null if there aren't any.
- */
- public String checkSkin(String skin) {
- if (mSkins != null) {
- for (Skin s : mSkins) {
- if (s.getName().equals(skin)) {
- return skin;
- }
- }
-
- if (mSkins.length > 0) {
- return mSkins[0].getName();
- }
- }
-
- return null;
- }
-
-
- /**
- * Returns the name of a skin by index.
- * @param index The index of the skin to return
- * @return the skin name of null if the index is invalid.
- */
- public String getSkinNameByIndex(int index) {
- if (mSkins != null) {
- if (index >= 0 && index < mSkins.length) {
- return mSkins[index].getName();
- }
- }
- return null;
- }
-
- /**
- * Returns the index (0 based) of the skin matching the name.
- * @param name The name of the skin to look for.
- * @return the index of the skin or -1 if the skin was not found.
- */
- public int getSkinIndex(String name) {
- if (mSkins != null) {
- int count = mSkins.length;
- for (int i = 0 ; i < count ; i++) {
- Skin s = mSkins[i];
- if (s.mName.equals(name)) {
- return i;
- }
- }
- }
-
- return -1;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
deleted file mode 100644
index 1c9a569..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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.editors.java;
-
-import org.eclipse.jdt.ui.PreferenceConstants;
-import org.eclipse.jdt.ui.text.IJavaPartitions;
-import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
-import org.eclipse.jdt.ui.text.JavaTextTools;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
-
-/**
- * Read only java editors. This looks like the regular Java editor, except that it
- * prevents editing the files. This is used for automatically generated java classes.
- */
-public class ReadOnlyJavaEditor extends AbstractDecoratedTextEditor {
-
- public final static String ID =
- "com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"; //$NON-NLS-1$
-
- public ReadOnlyJavaEditor() {
- IPreferenceStore javaUiStore = PreferenceConstants.getPreferenceStore();
- JavaTextTools jtt = new JavaTextTools(javaUiStore);
-
- JavaSourceViewerConfiguration jsvc = new JavaSourceViewerConfiguration(
- jtt.getColorManager(), javaUiStore, this, IJavaPartitions.JAVA_PARTITIONING);
-
- setSourceViewerConfiguration(jsvc);
- }
-
- @Override
- public boolean isEditable() {
- return false;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
index 136c0f3..434269c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
@@ -18,6 +18,9 @@ package com.android.ide.eclipse.adt.preferences;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.jarutils.DebugKeyProvider;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
@@ -29,6 +32,13 @@ import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
/**
* Preference page for build options.
*
@@ -75,7 +85,7 @@ public class BuildPreferencePage extends FieldEditorPreferencePage implements
addField(new ReadOnlyFieldEditor(AdtPlugin.PREFS_DEFAULT_DEBUG_KEYSTORE,
Messages.BuildPreferencePage_Default_KeyStore, getFieldEditorParent()));
- addField(new FileFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
+ addField(new KeystoreFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
Messages.BuildPreferencePage_Custom_Keystore, getFieldEditorParent()));
}
@@ -105,4 +115,103 @@ public class BuildPreferencePage extends FieldEditorPreferencePage implements
control.setEditable(false);
}
}
+
+ /**
+ * Custom {@link FileFieldEditor} that checks that the keystore is valid.
+ */
+ private static class KeystoreFieldEditor extends FileFieldEditor {
+ public KeystoreFieldEditor(String name, String label, Composite parent) {
+ super(name, label, parent);
+ setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+ }
+
+ @Override
+ protected boolean checkState() {
+ String fileName = getTextControl().getText();
+ fileName = fileName.trim();
+
+ // empty values are considered ok.
+ if (fileName.length() > 0) {
+ File file = new File(fileName);
+ if (file.isFile()) {
+ // attempt to load the debug key.
+ try {
+ DebugKeyProvider provider = new DebugKeyProvider(fileName,
+ null /* storeType */, null /* key gen output */);
+ PrivateKey key = provider.getDebugKey();
+ X509Certificate certificate = (X509Certificate)provider.getCertificate();
+
+ if (key == null || certificate == null) {
+ showErrorMessage("Unable to find debug key in keystore!");
+ return false;
+ }
+
+ Date today = new Date();
+ if (certificate.getNotAfter().compareTo(today) < 0) {
+ showErrorMessage("Certificate is expired!");
+ return false;
+ }
+
+ if (certificate.getNotBefore().compareTo(today) > 0) {
+ showErrorMessage("Certificate validity is in the future!");
+ return false;
+ }
+
+ // we're good!
+ clearErrorMessage();
+ return true;
+ } catch (GeneralSecurityException e) {
+ handleException(e);
+ return false;
+ } catch (IOException e) {
+ handleException(e);
+ return false;
+ } catch (KeytoolException e) {
+ handleException(e);
+ return false;
+ } catch (AndroidLocationException e) {
+ handleException(e);
+ return false;
+ }
+
+
+ } else {
+ // file does not exist.
+ showErrorMessage("Not a valid keystore path.");
+ return false; // Apply/OK must be disabled
+ }
+ }
+
+ clearErrorMessage();
+ return true;
+ }
+
+ @Override
+ public Text getTextControl(Composite parent) {
+ setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+ return super.getTextControl(parent);
+ }
+
+ /**
+ * Set the error message from a {@link Throwable}. If the exception has no message, try
+ * to get the message from the cause.
+ * @param t the Throwable.
+ */
+ private void handleException(Throwable t) {
+ String msg = t.getMessage();
+ if (t == null) {
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ handleException(cause);
+ } else {
+ setErrorMessage("Uknown error when getting the debug key!");
+ }
+
+ return;
+ }
+
+ // valid text, display it.
+ showErrorMessage(msg);
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
index efbbf94..a1b3c38 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.project;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -117,7 +118,7 @@ public class CreateAidlImportAction implements IObjectActionDelegate {
// create the file with the parcelables
if (parcelables.size() > 0) {
IPath path = project.getLocation();
- path = path.append("/project.aidl"); //$NON-NLS-1$
+ path = path.append(AndroidConstants.FN_PROJECT_AIDL);
File f = new File(path.toOSString());
if (f.exists() == false) {
@@ -194,7 +195,7 @@ public class CreateAidlImportAction implements IObjectActionDelegate {
IType[] superInterfaces = typeHierarchy.getAllSuperInterfaces(type);
for (IType superInterface : superInterfaces) {
- if ("android.os.Parcelable".equals(superInterface.getFullyQualifiedName())) { //$NON-NLS-1$
+ if (AndroidConstants.CLASS_PARCELABLE.equals(superInterface.getFullyQualifiedName())) {
parcelables.add(type.getFullyQualifiedName());
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
new file mode 100644
index 0000000..1ca89cd
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 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.project;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+
+/**
+ * A {@link ILabelDecorator} associated with an org.eclipse.ui.decorators extension.
+ * This is used to add android icons in some special folders in the package explorer.
+ */
+public class FolderDecorator implements ILightweightLabelDecorator {
+
+ private ImageDescriptor mDescriptor;
+
+ public FolderDecorator() {
+ mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png");
+ }
+
+ public void decorate(Object element, IDecoration decoration) {
+ if (element instanceof IFolder) {
+ IFolder folder = (IFolder)element;
+
+ // get the project and make sure this is an android project
+ IProject project = folder.getProject();
+
+ try {
+ if (project.hasNature(AndroidConstants.NATURE)) {
+ // check the folder is directly under the project.
+ if (folder.getParent().getType() == IResource.PROJECT) {
+ String name = folder.getName();
+ if (name.equals(AndroidConstants.FD_ASSETS)) {
+ decorate(decoration, " [Android assets]");
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ } else if (name.equals(AndroidConstants.FD_RESOURCES)) {
+ decorate(decoration, " [Android resources]");
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+ } else if (name.equals(AndroidConstants.FD_NATIVE_LIBS)) {
+ decorate(decoration, " [Native Libraries]");
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // log the error
+ AdtPlugin.log(e, "Unable to get nature of project '%s'.", project.getName());
+ }
+ }
+ }
+
+ public void decorate(IDecoration decoration, String suffix) {
+ decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+
+ // this is broken as it changes the color of the whole text, not only of the decoration.
+ // TODO: figure out how to change the color of the decoration only.
+// decoration.addSuffix(suffix);
+// ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
+// ColorRegistry registry = theme.getColorRegistry();
+// decoration.setForegroundColor(registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations"));
+
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ // at this time return false.
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ // No state change will affect the rendering.
+ }
+
+
+
+ public void removeListener(ILabelProviderListener listener) {
+ // No state change will affect the rendering.
+ }
+
+ public void dispose() {
+ // nothind to dispose
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
new file mode 100644
index 0000000..c117b4e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.project;
+
+import com.android.ide.eclipse.editors.wizards.NewXmlFileWizard;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class NewXmlFileWizardAction implements IObjectActionDelegate {
+
+ private ISelection mSelection;
+ private IWorkbench mWorkbench;
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ mWorkbench = targetPart.getSite().getWorkbenchWindow().getWorkbench();
+ }
+
+ public void run(IAction action) {
+ if (mSelection instanceof IStructuredSelection) {
+ IStructuredSelection selection = (IStructuredSelection)mSelection;
+
+ // call the new xml file wizard on the current selection.
+ NewXmlFileWizard wizard = new NewXmlFileWizard();
+ wizard.init(mWorkbench, selection);
+ WizardDialog dialog = new WizardDialog(mWorkbench.getDisplay().getActiveShell(),
+ wizard);
+ dialog.open();
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.mSelection = selection;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
index 24132b6..8678923 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
@@ -33,7 +33,6 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -178,31 +177,6 @@ public final class ProjectHelper {
}
/**
- * Check the validity of the javadoc attributes in a classpath entry.
- * @param frameworkEntry the classpath entry to check.
- * @return true if the javadoc attributes is valid, false otherwise.
- */
- public static boolean checkJavaDocPath(IClasspathEntry frameworkEntry) {
- // get the list of extra attributes
- IClasspathAttribute[] attributes = frameworkEntry.getExtraAttributes();
-
- // and search for the one about the javadoc
- for (IClasspathAttribute att : attributes) {
- if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.
- equals(att.getName())) {
- // we found a javadoc attribute. Now we test its value.
- // get the expect value
- String validJavaDoc = getJavaDocPath(AdtPlugin.getOsAbsoluteFramework());
-
- // now compare and return
- return validJavaDoc.equals(att.getValue());
- }
- }
-
- return false;
- }
-
- /**
* Fix the project. This checks the SDK location.
* @param project The project to fix.
* @throws JavaModelException
@@ -264,14 +238,7 @@ public final class ProjectHelper {
continue;
}
} else if (kind == IClasspathEntry.CPE_CONTAINER) {
- IPath containerPath = entry.getPath();
-
- if (AndroidClasspathContainerInitializer.checkOldPath(containerPath)) {
- entries = ProjectHelper.removeEntryFromClasspath(entries, i);
-
- // continue, to skip the i++;
- continue;
- } else if (AndroidClasspathContainerInitializer.checkPath(containerPath)) {
+ if (AndroidClasspathContainerInitializer.checkPath(entry.getPath())) {
foundContainer = true;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
index 1f51d09..de4b339 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
@@ -18,7 +18,10 @@ package com.android.ide.eclipse.adt.project.export;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.jarutils.KeystoreHelper;
import com.android.jarutils.SignedJarBuilder;
+import com.android.jarutils.DebugKeyProvider.IKeyGenOutput;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -27,28 +30,38 @@ import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IExportWizard;
import org.eclipse.ui.IWorkbench;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
+import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.KeyStore.PrivateKeyEntry;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
/**
* Export wizard to export an apk signed with a release key/certificate.
*/
-public class ExportWizard extends Wizard implements IExportWizard {
+public final class ExportWizard extends Wizard implements IExportWizard {
private static final String PROJECT_LOGO_LARGE = "icons/android_large.png"; //$NON-NLS-1$
- private static final String PAGE_PRE = "preExportPage"; //$NON-NLS-1$
- private static final String PAGE_SIGNING = "signingExportPage"; //$NON-NLS-1$
- private static final String PAGE_FINAL = "finalExportPage"; //$NON-NLS-1$
+ private static final String PAGE_PROJECT_CHECK = "Page_ProjectCheck"; //$NON-NLS-1$
+ private static final String PAGE_KEYSTORE_SELECTION = "Page_KeystoreSelection"; //$NON-NLS-1$
+ private static final String PAGE_KEY_CREATION = "Page_KeyCreation"; //$NON-NLS-1$
+ private static final String PAGE_KEY_SELECTION = "Page_KeySelection"; //$NON-NLS-1$
+ private static final String PAGE_KEY_CHECK = "Page_KeyCheck"; //$NON-NLS-1$
static final String PROPERTY_KEYSTORE = "keystore"; //$NON-NLS-1$
static final String PROPERTY_ALIAS = "alias"; //$NON-NLS-1$
@@ -59,7 +72,41 @@ public class ExportWizard extends Wizard implements IExportWizard {
*/
static abstract class ExportWizardPage extends WizardPage {
- protected boolean mNewProjectReference = true;
+ /** bit mask constant for project data change event */
+ protected static final int DATA_PROJECT = 0x001;
+ /** bit mask constant for keystore data change event */
+ protected static final int DATA_KEYSTORE = 0x002;
+ /** bit mask constant for key data change event */
+ protected static final int DATA_KEY = 0x004;
+
+ protected static final VerifyListener sPasswordVerifier = new VerifyListener() {
+ public void verifyText(VerifyEvent e) {
+ // verify the characters are valid for password.
+ int len = e.text.length();
+
+ // first limit to 127 characters max
+ if (len + ((Text)e.getSource()).getText().length() > 127) {
+ e.doit = false;
+ return;
+ }
+
+ // now only take non control characters
+ for (int i = 0 ; i < len ; i++) {
+ if (e.text.charAt(i) < 32) {
+ e.doit = false;
+ return;
+ }
+ }
+ }
+ };
+
+ /**
+ * Bit mask indicating what changed while the page was hidden.
+ * @see #DATA_PROJECT
+ * @see #DATA_KEYSTORE
+ * @see #DATA_KEY
+ */
+ protected int mProjectDataChanged = 0;
ExportWizardPage(String name) {
super(name);
@@ -72,23 +119,38 @@ public class ExportWizard extends Wizard implements IExportWizard {
super.setVisible(visible);
if (visible) {
onShow();
- mNewProjectReference = false;
+ mProjectDataChanged = 0;
}
}
- void newProjectReference() {
- mNewProjectReference = true;
+ final void projectDataChanged(int changeMask) {
+ mProjectDataChanged |= changeMask;
+ }
+
+ /**
+ * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
+ * {@link Throwable} object.
+ */
+ protected final void onException(Throwable t) {
+ String message = getExceptionMessage(t);
+
+ setErrorMessage(message);
+ setPageComplete(false);
}
}
- private ExportWizardPage mPages[] = new ExportWizardPage[3];
+ private ExportWizardPage mPages[] = new ExportWizardPage[5];
private IProject mProject;
private String mKeystore;
+ private String mKeystorePassword;
+ private boolean mKeystoreCreationMode;
+
private String mKeyAlias;
- private char[] mKeystorePassword;
- private char[] mKeyPassword;
+ private String mKeyPassword;
+ private int mValidity;
+ private String mDName;
private PrivateKey mPrivateKey;
private X509Certificate mCertificate;
@@ -97,6 +159,15 @@ public class ExportWizard extends Wizard implements IExportWizard {
private String mApkFilePath;
private String mApkFileName;
+ private ExportWizardPage mKeystoreSelectionPage;
+ private ExportWizardPage mKeyCreationPage;
+ private ExportWizardPage mKeySelectionPage;
+ private ExportWizardPage mKeyCheckPage;
+
+ private boolean mKeyCreationMode;
+
+ private List<String> mExistingAliases;
+
public ExportWizard() {
setHelpAvailable(false); // TODO have help
setWindowTitle("Export Android Application");
@@ -105,46 +176,101 @@ public class ExportWizard extends Wizard implements IExportWizard {
@Override
public void addPages() {
- addPage(mPages[0] = new PreExportPage(this, PAGE_PRE));
- addPage(mPages[1] = new SigningExportPage(this, PAGE_SIGNING));
- addPage(mPages[2] = new FinalExportPage(this, PAGE_FINAL));
+ addPage(mPages[0] = new ProjectCheckPage(this, PAGE_PROJECT_CHECK));
+ addPage(mKeystoreSelectionPage = mPages[1] = new KeystoreSelectionPage(this,
+ PAGE_KEYSTORE_SELECTION));
+ addPage(mKeyCreationPage = mPages[2] = new KeyCreationPage(this, PAGE_KEY_CREATION));
+ addPage(mKeySelectionPage = mPages[3] = new KeySelectionPage(this, PAGE_KEY_SELECTION));
+ addPage(mKeyCheckPage = mPages[4] = new KeyCheckPage(this, PAGE_KEY_CHECK));
}
@Override
public boolean performFinish() {
+ // first we make sure export is fine if the destination file already exists
+ File f = new File(mDestinationPath);
+ if (f.isFile()) {
+ if (AdtPlugin.displayPrompt("Export Wizard",
+ "File already exists. Do you want to overwrite it?") == false) {
+ return false;
+ }
+ }
+
// save the properties
ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore);
ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias);
ProjectHelper.saveStringProperty(mProject, PROPERTY_DESTINATION, mDestinationPath);
try {
- FileOutputStream fos = new FileOutputStream(mDestinationPath);
- SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
-
- // get the input file.
- FileInputStream fis = new FileInputStream(mApkFilePath);
- try {
- builder.writeZip(fis, null /* filter */);
- } finally {
+ if (mKeystoreCreationMode || mKeyCreationMode) {
+ final ArrayList<String> output = new ArrayList<String>();
+ if (KeystoreHelper.createNewStore(
+ mKeystore,
+ null /*storeType*/,
+ mKeystorePassword,
+ mKeyAlias,
+ mKeyPassword,
+ mDName,
+ mValidity,
+ new IKeyGenOutput() {
+ public void err(String message) {
+ output.add(message);
+ }
+ public void out(String message) {
+ output.add(message);
+ }
+ }) == false) {
+ // keystore creation error!
+ displayError(output.toArray(new String[output.size()]));
+ return false;
+ }
+
+ // keystore is created, now load the private key and certificate.
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mKeystore);
+ keyStore.load(fis, mKeystorePassword.toCharArray());
fis.close();
+ PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+ mKeyAlias, new KeyStore.PasswordProtection(mKeyPassword.toCharArray()));
+
+ if (entry != null) {
+ mPrivateKey = entry.getPrivateKey();
+ mCertificate = (X509Certificate)entry.getCertificate();
+ } else {
+ // this really shouldn't happen since we now let the user choose the key
+ // from a list read from the store.
+ displayError("Could not find key");
+ return false;
+ }
}
-
- builder.close();
- fos.close();
- return true;
+ // check the private key/certificate again since it may have been created just above.
+ if (mPrivateKey != null && mCertificate != null) {
+ FileOutputStream fos = new FileOutputStream(mDestinationPath);
+ SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
+
+ // get the input file.
+ FileInputStream fis = new FileInputStream(mApkFilePath);
+ try {
+ builder.writeZip(fis, null /* filter */);
+ } finally {
+ fis.close();
+ }
+
+ builder.close();
+ fos.close();
+
+ return true;
+ }
} catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
} catch (GeneralSecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ displayError(e);
+ } catch (KeytoolException e) {
+ displayError(e);
}
return false;
@@ -152,8 +278,13 @@ public class ExportWizard extends Wizard implements IExportWizard {
@Override
public boolean canFinish() {
+ // check if we have the apk to resign, the destination location, and either
+ // a private key/certificate or the creation mode. In creation mode, unless
+ // all the key/keystore info is valid, the user cannot reach the last page, so there's
+ // no need to check them again here.
return mApkFilePath != null &&
- mPrivateKey != null && mCertificate != null &&
+ ((mPrivateKey != null && mCertificate != null)
+ || mKeystoreCreationMode || mKeyCreationMode) &&
mDestinationPath != null;
}
@@ -175,6 +306,22 @@ public class ExportWizard extends Wizard implements IExportWizard {
}
}
+ ExportWizardPage getKeystoreSelectionPage() {
+ return mKeystoreSelectionPage;
+ }
+
+ ExportWizardPage getKeyCreationPage() {
+ return mKeyCreationPage;
+ }
+
+ ExportWizardPage getKeySelectionPage() {
+ return mKeySelectionPage;
+ }
+
+ ExportWizardPage getKeyCheckPage() {
+ return mKeyCheckPage;
+ }
+
/**
* Returns an image descriptor for the wizard logo.
*/
@@ -192,10 +339,7 @@ public class ExportWizard extends Wizard implements IExportWizard {
mApkFilePath = apkFilePath;
mApkFileName = filename;
- // indicate to the page that the project was changed.
- for (ExportWizardPage page : mPages) {
- page.newProjectReference();
- }
+ updatePageOnChange(ExportWizardPage.DATA_PROJECT);
}
String getApkFilename() {
@@ -206,42 +350,95 @@ public class ExportWizard extends Wizard implements IExportWizard {
mKeystore = path;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
}
String getKeystore() {
return mKeystore;
}
- void setKeyAlias(String name) {
- mKeyAlias = name;
- mPrivateKey = null;
- mCertificate = null;
+ void setKeystoreCreationMode(boolean createStore) {
+ mKeystoreCreationMode = createStore;
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
}
- String getKeyAlias() {
- return mKeyAlias;
+ boolean getKeystoreCreationMode() {
+ return mKeystoreCreationMode;
}
- void setKeystorePassword(char[] password) {
+
+ void setKeystorePassword(String password) {
mKeystorePassword = password;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
}
- char[] getKeystorePassword() {
+ String getKeystorePassword() {
return mKeystorePassword;
}
+
+ void setKeyCreationMode(boolean createKey) {
+ mKeyCreationMode = createKey;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ boolean getKeyCreationMode() {
+ return mKeyCreationMode;
+ }
+
+ void setExistingAliases(List<String> aliases) {
+ mExistingAliases = aliases;
+ }
- void setKeyPassword(char[] password) {
+ List<String> getExistingAliases() {
+ return mExistingAliases;
+ }
+
+ void setKeyAlias(String name) {
+ mKeyAlias = name;
+ mPrivateKey = null;
+ mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ String getKeyAlias() {
+ return mKeyAlias;
+ }
+
+ void setKeyPassword(String password) {
mKeyPassword = password;
mPrivateKey = null;
mCertificate = null;
+
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
}
- char[] getKeyPassword() {
+ String getKeyPassword() {
return mKeyPassword;
}
+ void setValidity(int validity) {
+ mValidity = validity;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ int getValidity() {
+ return mValidity;
+ }
+
+ void setDName(String dName) {
+ mDName = dName;
+ updatePageOnChange(ExportWizardPage.DATA_KEY);
+ }
+
+ String getDName() {
+ return mDName;
+ }
+
void setSigningInfo(PrivateKey privateKey, X509Certificate certificate) {
mPrivateKey = privateKey;
mCertificate = certificate;
@@ -251,4 +448,54 @@ public class ExportWizard extends Wizard implements IExportWizard {
mDestinationPath = path;
}
+ void updatePageOnChange(int changeMask) {
+ for (ExportWizardPage page : mPages) {
+ page.projectDataChanged(changeMask);
+ }
+ }
+
+ private void displayError(String... messages) {
+ String message = null;
+ if (messages.length == 1) {
+ message = messages[0];
+ } else {
+ StringBuilder sb = new StringBuilder(messages[0]);
+ for (int i = 1; i < messages.length; i++) {
+ sb.append('\n');
+ sb.append(messages[i]);
+ }
+
+ message = sb.toString();
+ }
+
+ AdtPlugin.displayError("Export Wizard", message);
+ }
+
+ private void displayError(Exception e) {
+ String message = getExceptionMessage(e);
+ displayError(message);
+
+ AdtPlugin.log(e, "Export Wizard Error");
+ }
+
+ /**
+ * Returns the {@link Throwable#getMessage()}. If the {@link Throwable#getMessage()} returns
+ * <code>null</code>, the method is called again on the cause of the Throwable object.
+ * <p/>If no Throwable in the chain has a valid message, the canonical name of the first
+ * exception is returned.
+ */
+ private static String getExceptionMessage(Throwable t) {
+ String message = t.getMessage();
+ if (message == null) {
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ return getExceptionMessage(cause);
+ }
+
+ // no more cause and still no message. display the first exception.
+ return cause.getClass().getCanonicalName();
+ }
+
+ return message;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
deleted file mode 100644
index 206e3aa..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2008 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.project.export;
-
-import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormText;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.UnrecoverableEntryException;
-import java.security.KeyStore.PrivateKeyEntry;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Calendar;
-
-public class FinalExportPage extends ExportWizardPage {
-
- private final ExportWizard mWizard;
- private PrivateKey mPrivateKey;
- private X509Certificate mCertificate;
- private Text mDestination;
- private Button mBrowseButton;
- private boolean mFatalSigningError;
- private FormText mDetailText;
-
- protected FinalExportPage(ExportWizard wizard, String pageName) {
- super(pageName);
- mWizard = wizard;
-
- setTitle("Application Export");
- setDescription("Export the signed Application package.");
- }
-
- public void createControl(Composite parent) {
- setErrorMessage(null);
- setMessage(null);
-
- // build the ui.
- Composite composite = new Composite(parent, SWT.NULL);
- composite.setLayoutData(new GridData(GridData.FILL_BOTH));
- GridLayout gl = new GridLayout(3, false);
- gl.verticalSpacing *= 3;
- composite.setLayout(gl);
-
- GridData gd;
-
- new Label(composite, SWT.NONE).setText("Destination APK file:");
- mDestination = new Text(composite, SWT.BORDER);
- mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- mDestination.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- onDestinationChange();
- }
- });
- mBrowseButton = new Button(composite, SWT.PUSH);
- mBrowseButton.setText("Browse...");
- mBrowseButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- FileDialog fileDialog = new FileDialog(mBrowseButton.getShell(), SWT.SAVE);
-
- fileDialog.setText("Destination file name");
- fileDialog.setFileName(mWizard.getApkFilename());
-
- String saveLocation = fileDialog.open();
- if (saveLocation != null) {
- mDestination.setText(saveLocation);
- }
- }
- });
-
- mDetailText = new FormText(composite, SWT.NONE);
- mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
- gd.horizontalSpan = 3;
-
- setControl(composite);
- }
-
- @Override
- void onShow() {
- // fill the texts with information loaded from the project.
- if (mNewProjectReference) {
- // reset the destination from the content of the project
- IProject project = mWizard.getProject();
-
- String destination = ProjectHelper.loadStringProperty(project,
- ExportWizard.PROPERTY_DESTINATION);
- if (destination != null) {
- mDestination.setText(destination);
- }
- }
-
- // reset the wizard with no key/cert to make it not finishable, unless a valid
- // key/cert is found.
- mWizard.setSigningInfo(null, null);
-
- try {
- KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- FileInputStream fis = new FileInputStream(mWizard.getKeystore());
- keyStore.load(fis, mWizard.getKeystorePassword());
- fis.close();
- PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
- mWizard.getKeyAlias(),
- new KeyStore.PasswordProtection(mWizard.getKeyPassword()));
-
- if (entry != null) {
- mPrivateKey = entry.getPrivateKey();
- mCertificate = (X509Certificate)entry.getCertificate();
- } else {
- setErrorMessage("Unable to find key");
-
- setPageComplete(false);
- }
- } catch (FileNotFoundException e) {
- // this was checked at the first previous step and will not happen here, unless
- // the file was removed during the export wizard execution.
- onException(e);
- } catch (KeyStoreException e) {
- onException(e);
- } catch (NoSuchAlgorithmException e) {
- onException(e);
- } catch (UnrecoverableEntryException e) {
- onException(e);
- } catch (CertificateException e) {
- onException(e);
- } catch (IOException e) {
- onException(e);
- }
-
- if (mPrivateKey != null && mCertificate != null) {
- mFatalSigningError = false;
-
- Calendar expirationCalendar = Calendar.getInstance();
- expirationCalendar.setTime(mCertificate.getNotAfter());
- Calendar today = Calendar.getInstance();
-
- if (expirationCalendar.before(today)) {
- mDetailText.setText(String.format("<form><p>Certificate expired on %s</p></form>",
- mCertificate.getNotAfter().toString()),
- true /* parseTags */, true /* expandURLs */);
-
- // fatal error = nothing can make the page complete.
- mFatalSigningError = true;
-
- setErrorMessage("Certificate is expired!");
- setPageComplete(false);
- } else {
- // valid, key/cert: put it in the wizard so that it can be finished
- mWizard.setSigningInfo(mPrivateKey, mCertificate);
-
- StringBuilder sb = new StringBuilder(String.format("<form><p>Certificate expires on %s.</p>",
- mCertificate.getNotAfter().toString()));
-
- int expirationYear = expirationCalendar.get(Calendar.YEAR);
- int thisYear = today.get(Calendar.YEAR);
-
- if (thisYear + 25 < expirationYear) {
- // do nothing
- } else {
- if (expirationYear == thisYear) {
- sb.append("<p>The certificate expires this year!</p>");
- } else {
- int count = expirationYear-thisYear;
- sb.append(String.format("<p>The Certificate expires in %1$s %2$s!</p>",
- count, count == 1 ? "year" : "years"));
- }
-
- sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
- sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
- sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
- sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
- sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
-
- sb.append("</form>");
- }
-
- mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
- }
- mDetailText.getParent().layout();
- } else {
- // fatal error = nothing can make the page complete.
- mFatalSigningError = true;
- }
-
- onDestinationChange();
- }
-
- private void onDestinationChange() {
- if (mFatalSigningError == false) {
- String path = mDestination.getText().trim();
- if (path.length() == 0) {
- setErrorMessage("Enter destination for the APK file.");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- File file = new File(path);
- if (file.isDirectory()) {
- setErrorMessage("Destination is a directory!");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- File parentFile = file.getParentFile();
- if (parentFile == null || parentFile.isDirectory() == false) {
- setErrorMessage("Not a valid directory.");
- mWizard.setDestination(null); // this is to reset canFinish in the wizard
- setPageComplete(false);
- } else {
- mWizard.setDestination(path);
- setErrorMessage(null);
- setPageComplete(true);
- }
- }
- }
- }
- }
-
- /**
- * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
- * {@link Throwable} object. If the {@link Throwable#getMessage()} returns <code>null</code>,
- * the method is called again on the cause of the Throwable.
- */
- private void onException(Throwable t) {
- String message = t.getMessage();
- if (message == null) {
- Throwable cause = t.getCause();
- if (cause != null) {
- onException(cause);
- } else {
- // no more cause and still no message. display the first exception.
- setErrorMessage(cause.getClass().getCanonicalName());
- setPageComplete(false);
- }
- return;
- }
-
- setErrorMessage(message);
- setPageComplete(false);
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
new file mode 100644
index 0000000..c64bf10
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormText;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableEntryException;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+
+/**
+ * Final page of the wizard that checks the key and ask for the ouput location.
+ */
+final class KeyCheckPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private PrivateKey mPrivateKey;
+ private X509Certificate mCertificate;
+ private Text mDestination;
+ private boolean mFatalSigningError;
+ private FormText mDetailText;
+
+ protected KeyCheckPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Destination and key/certificate checks");
+ setDescription(""); // TODO
+ }
+
+ public void createControl(Composite parent) {
+ setErrorMessage(null);
+ setMessage(null);
+
+ // build the ui.
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(3, false);
+ gl.verticalSpacing *= 3;
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ new Label(composite, SWT.NONE).setText("Destination APK file:");
+ mDestination = new Text(composite, SWT.BORDER);
+ mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mDestination.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onDestinationChange();
+ }
+ });
+ final Button browseButton = new Button(composite, SWT.PUSH);
+ browseButton.setText("Browse...");
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.SAVE);
+
+ fileDialog.setText("Destination file name");
+ fileDialog.setFileName(mWizard.getApkFilename());
+
+ String saveLocation = fileDialog.open();
+ if (saveLocation != null) {
+ mDestination.setText(saveLocation);
+ }
+ }
+ });
+
+ mDetailText = new FormText(composite, SWT.NONE);
+ mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
+ gd.horizontalSpan = 3;
+
+ setControl(composite);
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & DATA_PROJECT) != 0) {
+ // reset the destination from the content of the project
+ IProject project = mWizard.getProject();
+
+ String destination = ProjectHelper.loadStringProperty(project,
+ ExportWizard.PROPERTY_DESTINATION);
+ if (destination != null) {
+ mDestination.setText(destination);
+ }
+ }
+
+ // if anything change we basically reload the data.
+ if (mProjectDataChanged != 0) {
+ mFatalSigningError = false;
+
+ // reset the wizard with no key/cert to make it not finishable, unless a valid
+ // key/cert is found.
+ mWizard.setSigningInfo(null, null);
+
+ if (mWizard.getKeystoreCreationMode() || mWizard.getKeyCreationMode()) {
+ int validity = mWizard.getValidity();
+ StringBuilder sb = new StringBuilder(
+ String.format("<form><p>Certificate expires in %d years.</p>",
+ validity));
+
+ if (validity < 25) {
+ sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+ sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+ sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+ sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+ sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+ }
+
+ sb.append("</form>");
+ mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+ } else {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+ keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+ fis.close();
+ PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+ mWizard.getKeyAlias(),
+ new KeyStore.PasswordProtection(
+ mWizard.getKeyPassword().toCharArray()));
+
+ if (entry != null) {
+ mPrivateKey = entry.getPrivateKey();
+ mCertificate = (X509Certificate)entry.getCertificate();
+ } else {
+ setErrorMessage("Unable to find key.");
+
+ setPageComplete(false);
+ }
+ } catch (FileNotFoundException e) {
+ // this was checked at the first previous step and will not happen here, unless
+ // the file was removed during the export wizard execution.
+ onException(e);
+ } catch (KeyStoreException e) {
+ onException(e);
+ } catch (NoSuchAlgorithmException e) {
+ onException(e);
+ } catch (UnrecoverableEntryException e) {
+ onException(e);
+ } catch (CertificateException e) {
+ onException(e);
+ } catch (IOException e) {
+ onException(e);
+ }
+
+ if (mPrivateKey != null && mCertificate != null) {
+ Calendar expirationCalendar = Calendar.getInstance();
+ expirationCalendar.setTime(mCertificate.getNotAfter());
+ Calendar today = Calendar.getInstance();
+
+ if (expirationCalendar.before(today)) {
+ mDetailText.setText(String.format(
+ "<form><p>Certificate expired on %s</p></form>",
+ mCertificate.getNotAfter().toString()),
+ true /* parseTags */, true /* expandURLs */);
+
+ // fatal error = nothing can make the page complete.
+ mFatalSigningError = true;
+
+ setErrorMessage("Certificate is expired.");
+ setPageComplete(false);
+ } else {
+ // valid, key/cert: put it in the wizard so that it can be finished
+ mWizard.setSigningInfo(mPrivateKey, mCertificate);
+
+ StringBuilder sb = new StringBuilder(String.format(
+ "<form><p>Certificate expires on %s.</p>",
+ mCertificate.getNotAfter().toString()));
+
+ int expirationYear = expirationCalendar.get(Calendar.YEAR);
+ int thisYear = today.get(Calendar.YEAR);
+
+ if (thisYear + 25 < expirationYear) {
+ // do nothing
+ } else {
+ if (expirationYear == thisYear) {
+ sb.append("<p>The certificate expires this year.</p>");
+ } else {
+ int count = expirationYear-thisYear;
+ sb.append(String.format(
+ "<p>The Certificate expires in %1$s %2$s.</p>",
+ count, count == 1 ? "year" : "years"));
+ }
+
+ sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+ sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+ sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+ sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+ sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+ }
+
+ sb.append("</form>");
+
+ mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+ }
+ mDetailText.getParent().layout();
+ } else {
+ // fatal error = nothing can make the page complete.
+ mFatalSigningError = true;
+ }
+ }
+ }
+
+ onDestinationChange();
+ }
+
+ private void onDestinationChange() {
+ if (mFatalSigningError == false) {
+ // reset messages for now.
+ setErrorMessage(null);
+ setMessage(null);
+
+ String path = mDestination.getText().trim();
+
+ if (path.length() == 0) {
+ setErrorMessage("Enter destination for the APK file.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ File file = new File(path);
+ if (file.isDirectory()) {
+ setErrorMessage("Destination is a directory.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ File parentFile = file.getParentFile();
+ if (parentFile == null || parentFile.isDirectory() == false) {
+ setErrorMessage("Not a valid directory.");
+ mWizard.setDestination(null); // this is to reset canFinish in the wizard
+ setPageComplete(false);
+ return;
+ }
+
+ // no error, set the destination in the wizard.
+ mWizard.setDestination(path);
+ setPageComplete(true);
+
+ // However, we should also test if the file already exists.
+ if (file.isFile()) {
+ setMessage("Destination file already exists.", WARNING);
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
new file mode 100644
index 0000000..d7365f7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.util.List;
+
+/**
+ * Key creation page.
+ */
+final class KeyCreationPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private Text mAlias;
+ private Text mKeyPassword;
+ private Text mKeyPassword2;
+ private Text mCnField;
+ private boolean mDisableOnChange = false;
+ private Text mOuField;
+ private Text mOField;
+ private Text mLField;
+ private Text mStField;
+ private Text mCField;
+ private String mDName;
+ private int mValidity = 0;
+ private List<String> mExistingAliases;
+
+
+ protected KeyCreationPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Key Creation");
+ setDescription(""); // TODO?
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(2, false);
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ new Label(composite, SWT.NONE).setText("Alias:");
+ mAlias = new Text(composite, SWT.BORDER);
+ mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Password:");
+ mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeyPassword.addVerifyListener(sPasswordVerifier);
+
+ new Label(composite, SWT.NONE).setText("Confirm:");
+ mKeyPassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeyPassword2.addVerifyListener(sPasswordVerifier);
+
+ new Label(composite, SWT.NONE).setText("Validity (years):");
+ final Text validityText = new Text(composite, SWT.BORDER);
+ validityText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ validityText.addVerifyListener(new VerifyListener() {
+ public void verifyText(VerifyEvent e) {
+ // check for digit only.
+ for (int i = 0 ; i < e.text.length(); i++) {
+ char letter = e.text.charAt(i);
+ if (letter < '0' || letter > '9') {
+ e.doit = false;
+ return;
+ }
+ }
+ }
+ });
+
+ new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(
+ gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 2;
+
+ new Label(composite, SWT.NONE).setText("First and Last Name:");
+ mCnField = new Text(composite, SWT.BORDER);
+ mCnField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Organizational Unit:");
+ mOuField = new Text(composite, SWT.BORDER);
+ mOuField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Organization:");
+ mOField = new Text(composite, SWT.BORDER);
+ mOField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("City or Locality:");
+ mLField = new Text(composite, SWT.BORDER);
+ mLField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("State or Province:");
+ mStField = new Text(composite, SWT.BORDER);
+ mStField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ new Label(composite, SWT.NONE).setText("Country Code (XX):");
+ mCField = new Text(composite, SWT.BORDER);
+ mCField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+ // Show description the first time
+ setErrorMessage(null);
+ setMessage(null);
+ setControl(composite);
+
+ mAlias.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyAlias(mAlias.getText().trim());
+ onChange();
+ }
+ });
+ mKeyPassword.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyPassword(mKeyPassword.getText());
+ onChange();
+ }
+ });
+ mKeyPassword2.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onChange();
+ }
+ });
+
+ validityText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ try {
+ mValidity = Integer.parseInt(validityText.getText());
+ } catch (NumberFormatException e2) {
+ // this should only happen if the text field is empty due to the verifyListener.
+ mValidity = 0;
+ }
+ mWizard.setValidity(mValidity);
+ onChange();
+ }
+ });
+
+ ModifyListener dNameListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onDNameChange();
+ }
+ };
+
+ mCnField.addModifyListener(dNameListener);
+ mOuField.addModifyListener(dNameListener);
+ mOField.addModifyListener(dNameListener);
+ mLField.addModifyListener(dNameListener);
+ mStField.addModifyListener(dNameListener);
+ mCField.addModifyListener(dNameListener);
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+ // reset the keystore/alias from the content of the project
+ IProject project = mWizard.getProject();
+
+ // disable onChange for now. we'll call it once at the end.
+ mDisableOnChange = true;
+
+ String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
+ if (alias != null) {
+ mAlias.setText(alias);
+ }
+
+ // get the existing list of keys if applicable
+ if (mWizard.getKeyCreationMode()) {
+ mExistingAliases = mWizard.getExistingAliases();
+ } else {
+ mExistingAliases = null;
+ }
+
+ // reset the passwords
+ mKeyPassword.setText(""); //$NON-NLS-1$
+ mKeyPassword2.setText(""); //$NON-NLS-1$
+
+ // enable onChange, and call it to display errors and enable/disable pageCompleted.
+ mDisableOnChange = false;
+ onChange();
+ }
+ }
+
+ @Override
+ public IWizardPage getPreviousPage() {
+ if (mWizard.getKeyCreationMode()) { // this means we create a key from an existing store
+ return mWizard.getKeySelectionPage();
+ }
+
+ return mWizard.getKeystoreSelectionPage();
+ }
+
+ @Override
+ public IWizardPage getNextPage() {
+ return mWizard.getKeyCheckPage();
+ }
+
+ /**
+ * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+ */
+ private void onChange() {
+ if (mDisableOnChange) {
+ return;
+ }
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ if (mAlias.getText().trim().length() == 0) {
+ setErrorMessage("Enter key alias.");
+ setPageComplete(false);
+ return;
+ } else if (mExistingAliases != null) {
+ // we cannot use indexOf, because we need to do a case-insensitive check
+ String keyAlias = mAlias.getText().trim();
+ for (String alias : mExistingAliases) {
+ if (alias.equalsIgnoreCase(keyAlias)) {
+ setErrorMessage("Key alias already exists in keystore.");
+ setPageComplete(false);
+ return;
+ }
+ }
+ }
+
+ String value = mKeyPassword.getText();
+ if (value.length() == 0) {
+ setErrorMessage("Enter key password.");
+ setPageComplete(false);
+ return;
+ } else if (value.length() < 6) {
+ setErrorMessage("Key password is too short - must be at least 6 characters.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (value.equals(mKeyPassword2.getText()) == false) {
+ setErrorMessage("Key passwords don't match.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mValidity == 0) {
+ setErrorMessage("Key certificate validity is required.");
+ setPageComplete(false);
+ return;
+ } else if (mValidity < 25) {
+ setMessage("A 25 year certificate validity is recommended.", WARNING);
+ } else if (mValidity > 1000) {
+ setErrorMessage("Key certificate validity must be between 1 and 1000 years.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mDName == null || mDName.length() == 0) {
+ setErrorMessage("At least one Certificate issuer field is required to be non-empty.");
+ setPageComplete(false);
+ return;
+ }
+
+ setPageComplete(true);
+ }
+
+ /**
+ * Handles changes in the DName fields.
+ */
+ private void onDNameChange() {
+ StringBuilder sb = new StringBuilder();
+
+ buildDName("CN", mCnField, sb);
+ buildDName("OU", mOuField, sb);
+ buildDName("O", mOField, sb);
+ buildDName("L", mLField, sb);
+ buildDName("ST", mStField, sb);
+ buildDName("C", mCField, sb);
+
+ mDName = sb.toString();
+ mWizard.setDName(mDName);
+
+ onChange();
+ }
+
+ /**
+ * Builds the distinguished name string with the provided {@link StringBuilder}.
+ * @param prefix the prefix of the entry.
+ * @param textField The {@link Text} field containing the entry value.
+ * @param sb the string builder containing the dname.
+ */
+ private void buildDName(String prefix, Text textField, StringBuilder sb) {
+ if (textField != null) {
+ String value = textField.getText().trim();
+ if (value.length() > 0) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+
+ sb.append(prefix);
+ sb.append('=');
+ sb.append(value);
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
new file mode 100644
index 0000000..2fcd757
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Key Selection Page. This is used when an existing keystore is used.
+ */
+final class KeySelectionPage extends ExportWizardPage {
+
+ private final ExportWizard mWizard;
+ private Label mKeyAliasesLabel;
+ private Combo mKeyAliases;
+ private Label mKeyPasswordLabel;
+ private Text mKeyPassword;
+ private boolean mDisableOnChange = false;
+ private Button mUseExistingKey;
+ private Button mCreateKey;
+
+ protected KeySelectionPage(ExportWizard wizard, String pageName) {
+ super(pageName);
+ mWizard = wizard;
+
+ setTitle("Key alias selection");
+ setDescription(""); // TODO
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ GridLayout gl = new GridLayout(3, false);
+ composite.setLayout(gl);
+
+ GridData gd;
+
+ mUseExistingKey = new Button(composite, SWT.RADIO);
+ mUseExistingKey.setText("Use existing key");
+ mUseExistingKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+ mUseExistingKey.setSelection(true);
+
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = 0;
+ gd.widthHint = 50;
+ mKeyAliasesLabel = new Label(composite, SWT.NONE);
+ mKeyAliasesLabel.setText("Alias:");
+ mKeyAliases = new Combo(composite, SWT.READ_ONLY);
+ mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = 0;
+ gd.widthHint = 50;
+ mKeyPasswordLabel = new Label(composite, SWT.NONE);
+ mKeyPasswordLabel.setText("Password:");
+ mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ mCreateKey = new Button(composite, SWT.RADIO);
+ mCreateKey.setText("Create new key");
+ mCreateKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+
+ // Show description the first time
+ setErrorMessage(null);
+ setMessage(null);
+ setControl(composite);
+
+ mUseExistingKey.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mWizard.setKeyCreationMode(!mUseExistingKey.getSelection());
+ enableWidgets();
+ onChange();
+ }
+ });
+
+ mKeyAliases.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mWizard.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex()));
+ onChange();
+ }
+ });
+
+ mKeyPassword.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ mWizard.setKeyPassword(mKeyPassword.getText());
+ onChange();
+ }
+ });
+ }
+
+ @Override
+ void onShow() {
+ // fill the texts with information loaded from the project.
+ if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+ // disable onChange for now. we'll call it once at the end.
+ mDisableOnChange = true;
+
+ // reset the alias from the content of the project
+ try {
+ // reset to using a key
+ mWizard.setKeyCreationMode(false);
+ mUseExistingKey.setSelection(true);
+ mCreateKey.setSelection(false);
+ enableWidgets();
+
+ // remove the content of the alias combo always and first, in case the
+ // keystore password is wrong
+ mKeyAliases.removeAll();
+
+ // get the alias list (also used as a keystore password test)
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+ keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+ fis.close();
+
+ Enumeration<String> aliases = keyStore.aliases();
+
+ // get the alias from the project previous export, and look for a match as
+ // we add the aliases to the combo.
+ IProject project = mWizard.getProject();
+
+ String keyAlias = ProjectHelper.loadStringProperty(project,
+ ExportWizard.PROPERTY_ALIAS);
+
+ ArrayList<String> aliasList = new ArrayList<String>();
+
+ int selection = -1;
+ int count = 0;
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ mKeyAliases.add(alias);
+ aliasList.add(alias);
+ if (selection == -1 && alias.equalsIgnoreCase(keyAlias)) {
+ selection = count;
+ }
+ count++;
+ }
+
+ mWizard.setExistingAliases(aliasList);
+
+ if (selection != -1) {
+ mKeyAliases.select(selection);
+
+ // since a match was found and is selected, we need to give it to
+ // the wizard as well
+ mWizard.setKeyAlias(keyAlias);
+ } else {
+ mKeyAliases.clearSelection();
+ }
+
+ // reset the password
+ mKeyPassword.setText(""); //$NON-NLS-1$
+
+ // enable onChange, and call it to display errors and enable/disable pageCompleted.
+ mDisableOnChange = false;
+ onChange();
+ } catch (KeyStoreException e) {
+ onException(e);
+ } catch (FileNotFoundException e) {
+ onException(e);
+ } catch (NoSuchAlgorithmException e) {
+ onException(e);
+ } catch (CertificateException e) {
+ onException(e);
+ } catch (IOException e) {
+ onException(e);
+ } finally {
+ // in case we exit with an exception, we need to reset this
+ mDisableOnChange = false;
+ }
+ }
+ }
+
+ @Override
+ public IWizardPage getPreviousPage() {
+ return mWizard.getKeystoreSelectionPage();
+ }
+
+ @Override
+ public IWizardPage getNextPage() {
+ if (mWizard.getKeyCreationMode()) {
+ return mWizard.getKeyCreationPage();
+ }
+
+ return mWizard.getKeyCheckPage();
+ }
+
+ /**
+ * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+ */
+ private void onChange() {
+ if (mDisableOnChange) {
+ return;
+ }
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ if (mWizard.getKeyCreationMode() == false) {
+ if (mKeyAliases.getSelectionIndex() == -1) {
+ setErrorMessage("Select a key alias.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mKeyPassword.getText().trim().length() == 0) {
+ setErrorMessage("Enter key password.");
+ setPageComplete(false);
+ return;
+ }
+ }
+
+ setPageComplete(true);
+ }
+
+ private void enableWidgets() {
+ boolean useKey = !mWizard.getKeyCreationMode();
+ mKeyAliasesLabel.setEnabled(useKey);
+ mKeyAliases.setEnabled(useKey);
+ mKeyPassword.setEnabled(useKey);
+ mKeyPasswordLabel.setEnabled(useKey);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
index 5e7ed0f..c5a4d47 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
@@ -20,6 +20,7 @@ import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
@@ -36,23 +37,26 @@ import org.eclipse.swt.widgets.Text;
import java.io.File;
/**
- * Second export wizard page.
+ * Keystore selection page. This page allows to choose to create a new keystore or use an
+ * existing one.
*/
-public class SigningExportPage extends ExportWizardPage {
+final class KeystoreSelectionPage extends ExportWizardPage {
private final ExportWizard mWizard;
+ private Button mUseExistingKeystore;
+ private Button mCreateKeystore;
private Text mKeystore;
- private Text mAlias;
private Text mKeystorePassword;
- private Text mKeyPassword;
+ private Label mConfirmLabel;
+ private Text mKeystorePassword2;
private boolean mDisableOnChange = false;
- protected SigningExportPage(ExportWizard wizard, String pageName) {
+ protected KeystoreSelectionPage(ExportWizard wizard, String pageName) {
super(pageName);
mWizard = wizard;
- setTitle("Application Signing");
- setDescription("Defines which store, key and certificate to use to sign the Android Application.");
+ setTitle("Keystore selection");
+ setDescription(""); //TODO
}
public void createControl(Composite parent) {
@@ -62,8 +66,19 @@ public class SigningExportPage extends ExportWizardPage {
composite.setLayout(gl);
GridData gd;
+
+ mUseExistingKeystore = new Button(composite, SWT.RADIO);
+ mUseExistingKeystore.setText("Use existing keystore");
+ mUseExistingKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+ mUseExistingKeystore.setSelection(true);
+
+ mCreateKeystore = new Button(composite, SWT.RADIO);
+ mCreateKeystore.setText("Create new keystore");
+ mCreateKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
- new Label(composite, SWT.NONE).setText("Keystore:");
+ new Label(composite, SWT.NONE).setText("Location:");
mKeystore = new Text(composite, SWT.BORDER);
mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
final Button browseButton = new Button(composite, SWT.PUSH);
@@ -71,8 +86,14 @@ public class SigningExportPage extends ExportWizardPage {
browseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.OPEN);
- fileDialog.setText("Load Keystore");
+ FileDialog fileDialog;
+ if (mUseExistingKeystore.getSelection()) {
+ fileDialog = new FileDialog(browseButton.getShell(),SWT.OPEN);
+ fileDialog.setText("Load Keystore");
+ } else {
+ fileDialog = new FileDialog(browseButton.getShell(),SWT.SAVE);
+ fileDialog.setText("Select Keystore Name");
+ }
String fileName = fileDialog.open();
if (fileName != null) {
@@ -80,64 +101,73 @@ public class SigningExportPage extends ExportWizardPage {
}
}
});
-
- new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
- gd.horizontalSpan = 2;
- gd.heightHint = 0;
- new Button(composite, SWT.PUSH).setText("New...");
-
- new Label(composite, SWT.NONE).setText("Key Alias:");
- mAlias = new Text(composite, SWT.BORDER);
- mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-
- new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- gd.horizontalSpan = 3;
- new Label(composite, SWT.NONE).setText("Store password:");
+ new Label(composite, SWT.NONE).setText("Password:");
mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeystorePassword.addVerifyListener(sPasswordVerifier);
new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
gd.heightHint = gd.widthHint = 0;
- new Label(composite, SWT.NONE).setText("Key password:");
- mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
- mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mConfirmLabel = new Label(composite, SWT.NONE);
+ mConfirmLabel.setText("Confirm:");
+ mKeystorePassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+ mKeystorePassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ mKeystorePassword2.addVerifyListener(sPasswordVerifier);
+ new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+ gd.heightHint = gd.widthHint = 0;
+ mKeystorePassword2.setEnabled(false);
// Show description the first time
setErrorMessage(null);
setMessage(null);
setControl(composite);
- mKeystore.addModifyListener(new ModifyListener() {
- public void modifyText(ModifyEvent e) {
- mWizard.setKeystore(mKeystore.getText().trim());
- onChange();
+ mUseExistingKeystore.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ boolean createStore = !mUseExistingKeystore.getSelection();
+ mKeystorePassword2.setEnabled(createStore);
+ mConfirmLabel.setEnabled(createStore);
+ mWizard.setKeystoreCreationMode(createStore);
+ onChange();
}
});
- mAlias.addModifyListener(new ModifyListener() {
+
+ mKeystore.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
- mWizard.setKeyAlias(mAlias.getText().trim());
+ mWizard.setKeystore(mKeystore.getText().trim());
onChange();
}
});
+
mKeystorePassword.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
- mWizard.setKeystorePassword(mKeystorePassword.getText().trim().toCharArray());
+ mWizard.setKeystorePassword(mKeystorePassword.getText());
onChange();
}
});
- mKeyPassword.addModifyListener(new ModifyListener() {
+
+ mKeystorePassword2.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
- mWizard.setKeyPassword(mKeyPassword.getText().trim().toCharArray());
onChange();
}
});
}
@Override
+ public IWizardPage getNextPage() {
+ if (mUseExistingKeystore.getSelection()) {
+ return mWizard.getKeySelectionPage();
+ }
+
+ return mWizard.getKeyCreationPage();
+ }
+
+ @Override
void onShow() {
// fill the texts with information loaded from the project.
- if (mNewProjectReference) {
+ if ((mProjectDataChanged & DATA_PROJECT) != 0) {
// reset the keystore/alias from the content of the project
IProject project = mWizard.getProject();
@@ -150,14 +180,9 @@ public class SigningExportPage extends ExportWizardPage {
mKeystore.setText(keystore);
}
- String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
- if (alias != null) {
- mAlias.setText(alias);
- }
-
// reset the passwords
mKeystorePassword.setText(""); //$NON-NLS-1$
- mKeyPassword.setText(""); //$NON-NLS-1$
+ mKeystorePassword2.setText(""); //$NON-NLS-1$
// enable onChange, and call it to display errors and enable/disable pageCompleted.
mDisableOnChange = false;
@@ -176,6 +201,8 @@ public class SigningExportPage extends ExportWizardPage {
setErrorMessage(null);
setMessage(null);
+ boolean createStore = !mUseExistingKeystore.getSelection();
+
// checks the keystore path is non null.
String keystore = mKeystore.getText().trim();
if (keystore.length() == 0) {
@@ -185,32 +212,47 @@ public class SigningExportPage extends ExportWizardPage {
} else {
File f = new File(keystore);
if (f.exists() == false) {
- setErrorMessage("Keystore does not exists!");
- setPageComplete(false);
- return;
+ if (createStore == false) {
+ setErrorMessage("Keystore does not exist.");
+ setPageComplete(false);
+ return;
+ }
} else if (f.isDirectory()) {
- setErrorMessage("Keystore is a directory!");
+ setErrorMessage("Keystore path is a directory.");
setPageComplete(false);
return;
+ } else if (f.isFile()) {
+ if (createStore) {
+ setErrorMessage("File already exists.");
+ setPageComplete(false);
+ return;
+ }
}
}
- if (mAlias.getText().trim().length() == 0) {
- setErrorMessage("Enter key alias.");
+ String value = mKeystorePassword.getText();
+ if (value.length() == 0) {
+ setErrorMessage("Enter keystore password.");
setPageComplete(false);
return;
- }
-
- if (mKeystorePassword.getText().trim().length() == 0) {
- setErrorMessage("Enter keystore password.");
+ } else if (createStore && value.length() < 6) {
+ setErrorMessage("Keystore password is too short - must be at least 6 characters.");
setPageComplete(false);
return;
}
- if (mKeyPassword.getText().trim().length() == 0) {
- setErrorMessage("Enter key password.");
- setPageComplete(false);
- return;
+ if (createStore) {
+ if (mKeystorePassword2.getText().length() == 0) {
+ setErrorMessage("Confirm keystore password.");
+ setPageComplete(false);
+ return;
+ }
+
+ if (mKeystorePassword.getText().equals(mKeystorePassword2.getText()) == false) {
+ setErrorMessage("Keystore passwords do not match.");
+ setPageComplete(false);
+ return;
+ }
}
setPageComplete(true);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
index 5fc204d..3614be3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
@@ -47,7 +47,7 @@ import java.io.File;
/**
* First Export Wizard Page. Display warning/errors.
*/
-public class PreExportPage extends ExportWizardPage {
+final class ProjectCheckPage extends ExportWizardPage {
private final static String IMG_ERROR = "error.png"; //$NON-NLS-1$
private final static String IMG_WARNING = "warning.png"; //$NON-NLS-1$
@@ -60,12 +60,13 @@ public class PreExportPage extends ExportWizardPage {
private Composite mErrorComposite;
private Text mProjectText;
private ProjectChooserHelper mProjectChooserHelper;
+ private boolean mFirstOnShow = true;
- protected PreExportPage(ExportWizard wizard, String pageName) {
+ protected ProjectCheckPage(ExportWizard wizard, String pageName) {
super(pageName);
mWizard = wizard;
- setTitle("Pre Export Checks");
+ setTitle("Project Checks");
setDescription("Performs a set of checks to make sure the application can be exported.");
}
@@ -123,10 +124,14 @@ public class PreExportPage extends ExportWizardPage {
@Override
void onShow() {
- // get the project and init the ui
- IProject project = mWizard.getProject();
- if (project != null) {
- mProjectText.setText(project.getName());
+ if (mFirstOnShow) {
+ // get the project and init the ui
+ IProject project = mWizard.getProject();
+ if (project != null) {
+ mProjectText.setText(project.getName());
+ }
+
+ mFirstOnShow = false;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
index d7b290b..945fe52 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
@@ -27,16 +27,19 @@ class AndroidClasspathContainer implements IClasspathContainer {
private IClasspathEntry[] mClasspathEntry;
private IPath mContainerPath;
+ private String mName;
/**
* Constructs the container with the {@link IClasspathEntry} representing the android
* framework jar file and the container id
* @param entry the entry representing the android framework.
* @param path the path containing the classpath container id.
+ * @param name the name of the container to display.
*/
- AndroidClasspathContainer(IClasspathEntry entry, IPath path) {
+ AndroidClasspathContainer(IClasspathEntry entry, IPath path, String name) {
mClasspathEntry = new IClasspathEntry[] { entry };
mContainerPath = path;
+ mName = name;
}
public IClasspathEntry[] getClasspathEntries() {
@@ -44,7 +47,7 @@ class AndroidClasspathContainer implements IClasspathContainer {
}
public String getDescription() {
- return "Android Library";
+ return mName;
}
public int getKind() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
index 5dca350..2cafa01 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
@@ -16,10 +16,16 @@
package com.android.ide.eclipse.adt.project.internal;
+import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
+import com.android.sdklib.IAndroidTarget;
+import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -38,10 +44,6 @@ import org.eclipse.jdt.core.JavaModelException;
* {@link IProject}s. This removes the hard-coded path to the android.jar.
*/
public class AndroidClasspathContainerInitializer extends ClasspathContainerInitializer {
- /** The old container id */
- private final static String OLD_CONTAINER_ID =
- "com.android.ide.eclipse.adt.project.AndroidClasspathContainerInitializer"; //$NON-NLS-1$
-
/** The container id for the android framework jar file */
private final static String CONTAINER_ID =
"com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"; //$NON-NLS-1$
@@ -58,17 +60,10 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
*/
@Override
public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
- String id = null;
- if (OLD_CONTAINER_ID.equals(containerPath.toString())) {
- id = OLD_CONTAINER_ID;
- } else if (CONTAINER_ID.equals(containerPath.toString())) {
- id = CONTAINER_ID;
- }
-
- if (id != null) {
- JavaCore.setClasspathContainer(new Path(id),
+ if (CONTAINER_ID.equals(containerPath.toString())) {
+ JavaCore.setClasspathContainer(new Path(CONTAINER_ID),
new IJavaProject[] { project },
- new IClasspathContainer[] { allocateAndroidContainer(id) },
+ new IClasspathContainer[] { allocateAndroidContainer(CONTAINER_ID, project) },
new NullProgressMonitor());
}
}
@@ -82,15 +77,6 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
}
/**
- * Checks the {@link IPath} objects against the old android framework container id and
- * returns <code>true</code> if they are identical.
- * @param path the <code>IPath</code> to check.
- */
- public static boolean checkOldPath(IPath path) {
- return OLD_CONTAINER_ID.equals(path.toString());
- }
-
- /**
* Checks the {@link IPath} objects against the android framework container id and
* returns <code>true</code> if they are identical.
* @param path the <code>IPath</code> to check.
@@ -106,41 +92,18 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
* @return <code>true</code> if success, <code>false</code> otherwise.
*/
public static boolean updateProjects(IJavaProject[] androidProjects) {
-
try {
- // because those projects could have the old id, we are going to fix
- // them dynamically here.
- for (IJavaProject javaProject: androidProjects) {
- IClasspathEntry[] entries = javaProject.getRawClasspath();
-
- int containerIndex = ProjectHelper.findClasspathEntryByPath(entries,
- OLD_CONTAINER_ID,
- IClasspathEntry.CPE_CONTAINER);
- if (containerIndex != -1) {
- // the project has the old container, we remove it
- entries = ProjectHelper.removeEntryFromClasspath(entries, containerIndex);
-
- // we add the new one instead
- entries = ProjectHelper.addEntryToClasspath(entries, getContainerEntry());
-
- // and give the new entries to the project
- javaProject.setRawClasspath(entries, new NullProgressMonitor());
- }
- }
-
// Allocate a new AndroidClasspathContainer, and associate it to the android framework
// container id for each projects.
// By providing a new association between a container id and a IClasspathContainer,
// this forces the JDT to query the IClasspathContainer for new IClasspathEntry (with
// IClasspathContainer#getClasspathEntries()), and therefore force recompilation of
// the projects.
- // TODO: We could only do that for the projects haven't fixed above
- // (this isn't something that will happen a lot though)
int projectCount = androidProjects.length;
IClasspathContainer[] containers = new IClasspathContainer[projectCount];
for (int i = 0 ; i < projectCount; i++) {
- containers[i] = allocateAndroidContainer(CONTAINER_ID);
+ containers[i] = allocateAndroidContainer(CONTAINER_ID, androidProjects[i]);
}
// give each project their new container in one call.
@@ -158,23 +121,123 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
* Allocates and returns an {@link AndroidClasspathContainer} object with the proper
* path to the framework jar file.
* @param containerId the container id to be used.
+ * @param javaProject The java project that will receive the container.
*/
- private static IClasspathContainer allocateAndroidContainer(String containerId) {
- return new AndroidClasspathContainer(createFrameworkClasspath(), new Path(containerId));
+ private static IClasspathContainer allocateAndroidContainer(String containerId,
+ IJavaProject javaProject) {
+ IProject iProject = javaProject.getProject();
+
+ // remove potential MARKER_TARGETs.
+ try {
+ if (iProject.exists()) {
+ iProject.deleteMarkers(AdtConstants.MARKER_TARGET, true,
+ IResource.DEPTH_INFINITE);
+ }
+ } catch (CoreException ce) {
+ // just log the error
+ AdtPlugin.log(ce, "Error removing target marker.");
+ }
+
+
+ // first we check if the SDK has been loaded
+ boolean sdkIsLoaded = AdtPlugin.getDefault().getSdkLoadStatus(javaProject) ==
+ LoadStatus.LOADED;
+
+ // then we check if the project has a valid target.
+ IAndroidTarget target = null;
+ if (sdkIsLoaded) {
+ target = Sdk.getCurrent().getTarget(iProject);
+ }
+
+ // if we are loaded and the target is non null, we create a valid ClassPathContainer
+ if (sdkIsLoaded && target != null) {
+ String targetName = null;
+ if (target.isPlatform()) {
+ targetName = target.getName();
+ } else {
+ targetName = String.format("%1$s (%2$s)", target.getName(),
+ target.getApiVersionName());
+ }
+
+ return new AndroidClasspathContainer(createFrameworkClasspath(target),
+ new Path(containerId), targetName);
+ }
+
+ // else we put a marker on the project, and return a dummy container (to replace the
+ // previous one if there was one.)
+
+ // Get the project's target's hash string (if it exists)
+ String hashString = Sdk.getProjectTargetHashString(iProject);
+
+ String message = null;
+ boolean outputToConsole = true;
+ if (hashString == null || hashString.length() == 0) {
+ message = String.format(
+ "Project has no target set. Edit the project properties to set one.");
+ } else if (sdkIsLoaded) {
+ message = String.format(
+ "Unable to resolve target '%s'", hashString);
+ } else {
+ // this is the case where there is a hashString but the SDK is not yet
+ // loaded and therefore we can't get the target yet.
+ message = String.format(
+ "Unable to resolve target '%s' until the SDK is loaded.", hashString);
+
+ // let's not log this one to the console as it will happen at every boot,
+ // and it's expected. (we do keep the error marker though).
+ outputToConsole = false;
+ }
+
+ // log the error and put the marker on the project
+ if (outputToConsole) {
+ AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject, message);
+ }
+ IMarker marker = BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET, message,
+ IMarker.SEVERITY_ERROR);
+
+ // add a marker priority as this is an more important error than the error that will
+ // spring from the lack of library
+ try {
+ marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+ } catch (CoreException e) {
+ // just log the error
+ AdtPlugin.log(e, "Error changing target marker priority.");
+ }
+
+ // return a dummy container to replace the one we may have had before.
+ return new IClasspathContainer() {
+ public IClasspathEntry[] getClasspathEntries() {
+ return new IClasspathEntry[0];
+ }
+
+ public String getDescription() {
+ return "Unable to get system library for the project";
+ }
+
+ public int getKind() {
+ return IClasspathContainer.K_DEFAULT_SYSTEM;
+ }
+
+ public IPath getPath() {
+ return null;
+ }
+ };
}
/**
- * Creates and returns a new {@link IClasspathEntry} object for the android framework.
- * <p/>This references the OS path to the android.jar and the java doc directory. This is
- * dynamically created when a project is opened, and never saved in the project itself, so
- * there's no risk of storing an obsolete path.
+ * Creates and returns a new {@link IClasspathEntry} object for the android
+ * framework. <p/>This references the OS path to the android.jar and the
+ * java doc directory. This is dynamically created when a project is opened,
+ * and never saved in the project itself, so there's no risk of storing an
+ * obsolete path.
+ *
+ * @param target The target that contains the libraries.
*/
- private static IClasspathEntry createFrameworkClasspath() {
+ private static IClasspathEntry createFrameworkClasspath(IAndroidTarget target) {
// now add the android framework to the class path.
// create the path object.
- IPath android_lib = new Path(AdtPlugin.getOsAbsoluteFramework());
-
- IPath android_src = new Path(AdtPlugin.getOsAbsoluteAndroidSources());
+ IPath android_lib = new Path(target.getPath(IAndroidTarget.ANDROID_JAR));
+ IPath android_src = new Path(target.getPath(IAndroidTarget.SOURCES));
// create the java doc link.
IClasspathAttribute cpAttribute = JavaCore.newClasspathAttribute(
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
new file mode 100644
index 0000000..584dd0d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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.project.properties;
+
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page for "Android" project.
+ * This is accessible from the Package Explorer when right clicking a project and choosing
+ * "Properties".
+ *
+ */
+public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPropertyPage {
+
+ private IProject mProject;
+ private SdkTargetSelector mSelector;
+
+ public AndroidPropertyPage() {
+ // pass
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ // get the element (this is not yet valid in the constructor).
+ mProject = (IProject)getElement();
+
+ Composite top = new Composite(parent, SWT.NONE);
+ top.setLayoutData(new GridData(GridData.FILL_BOTH));
+ top.setLayout(new GridLayout(1, false));
+
+ Label l = new Label(top, SWT.NONE);
+ l.setText("Project Target");
+
+ // get the targets from the sdk
+ IAndroidTarget[] targets = null;
+ if (Sdk.getCurrent() != null) {
+ targets = Sdk.getCurrent().getTargets();
+ }
+
+ // build the UI.
+ mSelector = new SdkTargetSelector(top, targets, false /*allowMultipleSelection*/);
+
+ if (Sdk.getCurrent() != null) {
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+ if (target != null) {
+ mSelector.setSelection(target);
+ }
+ }
+
+ mSelector.setSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ // look for the selection and validate the page if there is a selection
+ IAndroidTarget target = mSelector.getFirstSelected();
+ setValid(target != null);
+ }
+ });
+
+ return top;
+ }
+
+ @Override
+ public boolean performOk() {
+ if (Sdk.getCurrent() != null) {
+ Sdk.getCurrent().setProject(mProject, mSelector.getFirstSelected());
+ }
+
+ return true;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
index 8c37f05..fad4f19 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -35,9 +34,12 @@ import javax.management.InvalidAttributeValueException;
/**
* Custom class loader able to load a class from the SDK jar file.
*/
-public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
+public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader {
- public final static class ClassWrapper implements IClass {
+ /**
+ * Wrapper around a {@link Class} to provide the methods of {@link IClassDescriptor}.
+ */
+ public final static class ClassWrapper implements IClassDescriptor {
private Class<?> mClass;
public ClassWrapper(Class<?> clazz) {
@@ -48,9 +50,9 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
return mClass.getCanonicalName();
}
- public IClass[] getDeclaredClasses() {
+ public IClassDescriptor[] getDeclaredClasses() {
Class<?>[] classes = mClass.getDeclaredClasses();
- IClass[] iclasses = new IClass[classes.length];
+ IClassDescriptor[] iclasses = new IClassDescriptor[classes.length];
for (int i = 0 ; i < classes.length ; i++) {
iclasses[i] = new ClassWrapper(classes[i]);
}
@@ -58,7 +60,7 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
return iclasses;
}
- public IClass getEnclosingClass() {
+ public IClassDescriptor getEnclosingClass() {
return new ClassWrapper(mClass.getEnclosingClass());
}
@@ -66,7 +68,7 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
return mClass.getSimpleName();
}
- public IClass getSuperclass() {
+ public IClassDescriptor getSuperclass() {
return new ClassWrapper(mClass.getSuperclass());
}
@@ -131,17 +133,18 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
* @param packageFilter The package that contains all the class data to preload, using a fully
* qualified binary name (.e.g "com.my.package."). The matching algorithm
* is simple "startsWith". Use an empty string to include everything.
+ * @param taskLabel An optional task name for the sub monitor. Can be null.
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
* @throws IOException
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public void preLoadClasses(String packageFilter, IProgressMonitor monitor)
+ public void preLoadClasses(String packageFilter, String taskLabel, IProgressMonitor monitor)
throws IOException, InvalidAttributeValueException, ClassFormatError {
// Transform the package name into a zip entry path
String pathFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
- SubMonitor progress = SubMonitor.convert(monitor, 100);
+ SubMonitor progress = SubMonitor.convert(monitor, taskLabel == null ? "" : taskLabel, 100);
// create streams to read the intermediary archive
FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
@@ -174,6 +177,7 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
// advance 5% of whatever is allocated on the progress bar
progress.setWorkRemaining(100);
progress.worked(5);
+ progress.subTask(String.format("Preload %1$s", className));
}
}
@@ -193,17 +197,18 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String packageFilter,
String[] superClasses)
throws IOException, InvalidAttributeValueException, ClassFormatError {
packageFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
- HashMap<String, ArrayList<IClass>> mClassesFound = new HashMap<String, ArrayList<IClass>>();
+ HashMap<String, ArrayList<IClassDescriptor>> mClassesFound =
+ new HashMap<String, ArrayList<IClassDescriptor>>();
for (String className : superClasses) {
- mClassesFound.put(className, new ArrayList<IClass>());
+ mClassesFound.put(className, new ArrayList<IClassDescriptor>());
}
// create streams to read the intermediary archive
@@ -415,7 +420,7 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException {
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException {
try {
return new ClassWrapper(loadClass(className));
} catch (ClassNotFoundException e) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
new file mode 100644
index 0000000..60561ab
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2007 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.sdk;
+
+import com.android.ide.eclipse.common.resources.IResourceRepository;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * This class contains the data of an Android Target as loaded from the SDK.
+ */
+public class AndroidTargetData {
+
+ public final static int DESCRIPTOR_MANIFEST = 1;
+ public final static int DESCRIPTOR_LAYOUT = 2;
+ public final static int DESCRIPTOR_MENU = 3;
+ public final static int DESCRIPTOR_XML = 4;
+ public final static int DESCRIPTOR_RESOURCES = 5;
+ public final static int DESCRIPTOR_SEARCHABLE = 6;
+ public final static int DESCRIPTOR_PREFERENCES = 7;
+
+ public final static class LayoutBridge {
+ /** Link to the layout bridge */
+ public ILayoutBridge bridge;
+
+ public LoadStatus status = LoadStatus.LOADING;
+
+ public ClassLoader classLoader;
+ }
+
+ private final IAndroidTarget mTarget;
+
+ /**
+ * mAttributeValues is a map { key => list [ values ] }.
+ * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
+ * The attribute namespace prefix must be:
+ * - "android" for AndroidConstants.NS_RESOURCES
+ * - "xmlns" for the XMLNS URI.
+ *
+ * This is used for attributes that do not have a unique name, but still need to be populated
+ * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
+ */
+ private final Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
+
+ private IResourceRepository mSystemResourceRepository;
+
+ private final AndroidManifestDescriptors mManifestDescriptors;
+ private final LayoutDescriptors mLayoutDescriptors;
+ private final MenuDescriptors mMenuDescriptors;
+ private final XmlDescriptors mXmlDescriptors;
+
+ private final Map<String, Map<String, Integer>> mEnumValueMap;
+
+ private final ProjectResources mFrameworkResources;
+ private final LayoutBridge mLayoutBridge;
+
+ private boolean mLayoutBridgeInit = false;
+
+ /**
+ * Creates an AndroidTargetData object.
+ */
+ AndroidTargetData(IAndroidTarget androidTarget,
+ IResourceRepository systemResourceRepository,
+ AndroidManifestDescriptors manifestDescriptors,
+ LayoutDescriptors layoutDescriptors,
+ MenuDescriptors menuDescriptors,
+ XmlDescriptors xmlDescriptors,
+ Map<String, Map<String, Integer>> enumValueMap,
+ String[] permissionValues,
+ String[] activityIntentActionValues,
+ String[] broadcastIntentActionValues,
+ String[] serviceIntentActionValues,
+ String[] intentCategoryValues,
+ ProjectResources resources,
+ LayoutBridge layoutBridge) {
+
+ mTarget = androidTarget;
+ mSystemResourceRepository = systemResourceRepository;
+ mManifestDescriptors = manifestDescriptors;
+ mLayoutDescriptors = layoutDescriptors;
+ mMenuDescriptors = menuDescriptors;
+ mXmlDescriptors = xmlDescriptors;
+ mEnumValueMap = enumValueMap;
+ mFrameworkResources = resources;
+ mLayoutBridge = layoutBridge;
+
+ setPermissions(permissionValues);
+ setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
+ serviceIntentActionValues, intentCategoryValues);
+ }
+
+ public IResourceRepository getSystemResources() {
+ return mSystemResourceRepository;
+ }
+
+ /**
+ * Returns an {@link IDescriptorProvider} from a given Id.
+ * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
+ * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_XML}.
+ * All other values will throw an {@link IllegalArgumentException}.
+ */
+ public IDescriptorProvider getDescriptorProvider(int descriptorId) {
+ switch (descriptorId) {
+ case DESCRIPTOR_MANIFEST:
+ return mManifestDescriptors;
+ case DESCRIPTOR_LAYOUT:
+ return mLayoutDescriptors;
+ case DESCRIPTOR_MENU:
+ return mMenuDescriptors;
+ case DESCRIPTOR_XML:
+ return mXmlDescriptors;
+ case DESCRIPTOR_RESOURCES:
+ // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
+ return ResourcesDescriptors.getInstance();
+ case DESCRIPTOR_PREFERENCES:
+ return mXmlDescriptors.getPreferencesProvider();
+ case DESCRIPTOR_SEARCHABLE:
+ return mXmlDescriptors.getSearchableProvider();
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Returns the manifest descriptors.
+ */
+ public AndroidManifestDescriptors getManifestDescriptors() {
+ return mManifestDescriptors;
+ }
+
+ /**
+ * Returns the layout Descriptors.
+ */
+ public LayoutDescriptors getLayoutDescriptors() {
+ return mLayoutDescriptors;
+ }
+
+ /**
+ * Returns the menu descriptors.
+ */
+ public MenuDescriptors getMenuDescriptors() {
+ return mMenuDescriptors;
+ }
+
+ /**
+ * Returns the XML descriptors
+ */
+ public XmlDescriptors getXmlDescriptors() {
+ return mXmlDescriptors;
+ }
+
+ /**
+ * Returns this list of possible values for an XML attribute.
+ * <p/>This should only be called for attributes for which possible values depend on the
+ * parent element node.
+ * <p/>For attributes that have the same values no matter the parent node, use
+ * {@link #getEnumValueMap()}.
+ * @param elementName the name of the element containing the attribute.
+ * @param attributeName the name of the attribute
+ * @return an array of String with the possible values, or <code>null</code> if no values were
+ * found.
+ */
+ public String[] getAttributeValues(String elementName, String attributeName) {
+ String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
+ return mAttributeValues.get(key);
+ }
+
+ /**
+ * Returns this list of possible values for an XML attribute.
+ * <p/>This should only be called for attributes for which possible values depend on the
+ * parent and great-grand-parent element node.
+ * <p/>The typical example of this is for the 'name' attribute under
+ * activity/intent-filter/action
+ * <p/>For attributes that have the same values no matter the parent node, use
+ * {@link #getEnumValueMap()}.
+ * @param elementName the name of the element containing the attribute.
+ * @param attributeName the name of the attribute
+ * @param greatGrandParentElementName the great-grand-parent node.
+ * @return an array of String with the possible values, or <code>null</code> if no values were
+ * found.
+ */
+ public String[] getAttributeValues(String elementName, String attributeName,
+ String greatGrandParentElementName) {
+ if (greatGrandParentElementName != null) {
+ String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
+ greatGrandParentElementName, elementName, attributeName);
+ String[] values = mAttributeValues.get(key);
+ if (values != null) {
+ return values;
+ }
+ }
+
+ return getAttributeValues(elementName, attributeName);
+ }
+
+ /**
+ * Returns the enum values map.
+ * <p/>The map defines the possible values for XML attributes. The key is the attribute name
+ * and the value is a map of (string, integer) in which the key (string) is the name of
+ * the value, and the Integer is the numerical value in the compiled binary XML files.
+ */
+ public Map<String, Map<String, Integer>> getEnumValueMap() {
+ return mEnumValueMap;
+ }
+
+ /**
+ * Returns the {@link ProjectResources} containing the Framework Resources.
+ */
+ public ProjectResources getFrameworkResources() {
+ return mFrameworkResources;
+ }
+
+ /**
+ * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
+ * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
+ * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
+ * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
+ */
+ public synchronized LayoutBridge getLayoutBridge() {
+ if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
+ mLayoutBridge.bridge.init(mTarget.getPath(IAndroidTarget.FONTS),
+ getEnumValueMap());
+ mLayoutBridgeInit = true;
+ }
+ return mLayoutBridge;
+ }
+
+ /**
+ * Sets the permission values
+ * @param permissionValues the list of permissions
+ */
+ private void setPermissions(String[] permissionValues) {
+ setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
+ setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
+ setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
+ }
+
+ private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
+ String[] broadcastIntentActions, String[] serviceIntentActions,
+ String[] intentCategoryValues) {
+ setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
+ setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
+ setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
+ setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets a (name, values) pair in the hash map.
+ * <p/>
+ * If the name is already present in the map, it is first removed.
+ * @param name the name associated with the values.
+ * @param values The values to add.
+ */
+ private void setValues(String name, String[] values) {
+ mAttributeValues.remove(name);
+ mAttributeValues.put(name, values);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
index 703efcf..232b9e8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2008 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.
@@ -14,19 +14,29 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import java.io.BufferedReader;
@@ -34,10 +44,11 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
import java.net.URL;
+import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -48,7 +59,7 @@ import java.util.Map;
import javax.management.InvalidAttributeValueException;
/**
- * Parser for the framework library.
+ * Parser for the platform data in an SDK.
* <p/>
* This gather the following information:
* <ul>
@@ -57,14 +68,16 @@ import javax.management.InvalidAttributeValueException;
* <li></li>
* </ul>
*/
-public final class FrameworkResourceParser {
+public final class AndroidTargetParser {
private static final String TAG = "Framework Resource Parser";
+ private final IAndroidTarget mAndroidTarget;
/**
- * Creates a framework resource parser.
+ * Creates a platform data parser.
*/
- public FrameworkResourceParser() {
+ public AndroidTargetParser(IAndroidTarget platformTarget) {
+ mAndroidTarget = platformTarget;
}
/**
@@ -77,34 +90,29 @@ public final class FrameworkResourceParser {
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
* @return True if the SDK path was valid and parsing has been attempted.
*/
- public boolean parse(String osSdkPath, FrameworkResourceManager resourceManager,
- IProgressMonitor monitor) {
- if (osSdkPath == null || osSdkPath.length() == 0) {
- return false;
- }
-
+ public IStatus run(IProgressMonitor monitor) {
try {
- SubMonitor progress = SubMonitor.convert(monitor, 100);
+ SubMonitor progress = SubMonitor.convert(monitor,
+ String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
+ 120);
AndroidJarLoader classLoader =
- new AndroidJarLoader(osSdkPath + AndroidConstants.FN_FRAMEWORK_LIBRARY);
+ new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
- progress.subTask("Preloading");
- preload(classLoader, progress.newChild(40));
- progress.setWorkRemaining(60);
+ preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
+ progress.setWorkRemaining(80);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
// get the resource Ids.
progress.subTask("Resource IDs");
- FrameworkResourceRepository systemResourceRepository = new FrameworkResourceRepository(
- collectResourceIds(classLoader));
+ IResourceRepository frameworkRepository = collectResourceIds(classLoader);
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
// get the permissions
@@ -113,56 +121,59 @@ public final class FrameworkResourceParser {
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- String osLibPath = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
// get the action and category values for the Intents.
progress.subTask("Intents");
ArrayList<String> activity_actions = new ArrayList<String>();
ArrayList<String> broadcast_actions = new ArrayList<String>();
ArrayList<String> service_actions = new ArrayList<String>();
ArrayList<String> categories = new ArrayList<String>();
- collectIntentFilterActionsAndCategories(osLibPath,
- activity_actions, broadcast_actions, service_actions, categories);
+ collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
+ service_actions, categories);
progress.worked(5);
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- progress.subTask("Layouts");
+ // gather the attribute definition
+ progress.subTask("Attributes definitions");
AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
- osSdkPath + AndroidConstants.OS_SDK_ATTRS_XML);
+ mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES));
attrsXmlParser.preload();
+ progress.subTask("Manifest definitions");
AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
- osSdkPath + AndroidConstants.OS_SDK_ATTRS_MANIFEST_XML,
+ mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
attrsXmlParser);
attrsManifestXmlParser.preload();
Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
- collectLayoutClasses(osLibPath, classLoader, attrsXmlParser, mainList, groupList,
+ // collect the layout/widgets classes
+ progress.subTask("Widgets and layouts");
+ collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(40));
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
ViewClassInfo[] layoutViewsInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
new ViewClassInfo[groupList.size()]);
+ // collect the preferences classes.
mainList.clear();
groupList.clear();
collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
progress.newChild(5));
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
@@ -177,34 +188,77 @@ public final class FrameworkResourceParser {
Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
if (progress.isCanceled()) {
- return false;
+ return Status.CANCEL_STATUS;
}
- String docBaseUrl = getDocumentationBaseUrl(
- osSdkPath + AndroidConstants.OS_SDK_DOCS_FOLDER);
-
- FrameworkResourceManager.getInstance().setResources(systemResourceRepository,
- layoutViewsInfo,
- layoutGroupsInfo,
- preferencesInfo,
- preferenceGroupsInfo,
- xmlMenuMap,
- xmlSearchableMap,
- manifestMap,
+ // From the information that was collected, create the pieces that will be put in
+ // the PlatformData object.
+ AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors();
+ manifestDescriptors.updateDescriptors(manifestMap);
+ progress.worked(10);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
+ layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo);
+ progress.worked(10);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ MenuDescriptors menuDescriptors = new MenuDescriptors();
+ menuDescriptors.updateDescriptors(xmlMenuMap);
+ progress.worked(10);
+
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ XmlDescriptors xmlDescriptors = new XmlDescriptors();
+ xmlDescriptors.updateDescriptors(xmlSearchableMap, preferencesInfo,
+ preferenceGroupsInfo);
+ progress.worked(10);
+
+ // load the framework resources.
+ ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
+ mAndroidTarget);
+ progress.worked(10);
+
+ // now load the layout lib bridge
+ LayoutBridge layoutBridge = loadLayoutBridge();
+ progress.worked(10);
+
+ // and finally create the PlatformData with all that we loaded.
+ AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget,
+ frameworkRepository,
+ manifestDescriptors,
+ layoutDescriptors,
+ menuDescriptors,
+ xmlDescriptors,
enumValueMap,
permissionValues,
activity_actions.toArray(new String[activity_actions.size()]),
broadcast_actions.toArray(new String[broadcast_actions.size()]),
service_actions.toArray(new String[service_actions.size()]),
categories.toArray(new String[categories.size()]),
- docBaseUrl);
+ resources,
+ layoutBridge);
+
+ Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
- return true;
+ return Status.OK_STATUS;
} catch (Exception e) {
AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
+ AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
+ } finally {
+ if (monitor != null) {
+ monitor.done();
+ }
}
-
- return false;
}
/**
@@ -217,7 +271,9 @@ public final class FrameworkResourceParser {
*/
private void preload(AndroidJarLoader classLoader, IProgressMonitor monitor) {
try {
- classLoader.preLoadClasses("" /* all classes */, monitor); //$NON-NLS-1$
+ classLoader.preLoadClasses("" /* all classes */, //$NON-NLS-1$
+ mAndroidTarget.getName(), // monitor task label
+ monitor);
} catch (InvalidAttributeValueException e) {
AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
} catch (IOException e) {
@@ -226,24 +282,27 @@ public final class FrameworkResourceParser {
}
/**
- * Collects the resources IDs found in the SDK.
+ * Creates an IResourceRepository for the framework resources.
*
* @param classLoader The framework SDK jar classloader
* @return a map of the resources, or null if it failed.
*/
- private Map<ResourceType, List<ResourceItem>> collectResourceIds(
+ private IResourceRepository collectResourceIds(
AndroidJarLoader classLoader) {
try {
Class<?> r = classLoader.loadClass(AndroidConstants.CLASS_R);
if (r != null) {
- return parseRClass(r);
+ Map<ResourceType, List<ResourceItem>> map = parseRClass(r);
+ if (map != null) {
+ return new FrameworkResourceRepository(map);
+ }
}
} catch (ClassNotFoundException e) {
AdtPlugin.logAndPrintError(e, TAG,
"Collect resource IDs failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_R,
- classLoader.getSource());
+ mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return null;
@@ -331,7 +390,7 @@ public final class FrameworkResourceParser {
AdtPlugin.logAndPrintError(e, TAG,
"Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
AndroidConstants.CLASS_MANIFEST_PERMISSION,
- classLoader.getSource());
+ mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
}
return new String[0];
@@ -347,13 +406,17 @@ public final class FrameworkResourceParser {
* @param serviceActions the list which will receive the service action values.
* @param categories the list which will receive the category values.
*/
- private void collectIntentFilterActionsAndCategories(String osLibPath,
- ArrayList<String> activityActions, ArrayList<String> broadcastActions,
+ private void collectIntentFilterActionsAndCategories(ArrayList<String> activityActions,
+ ArrayList<String> broadcastActions,
ArrayList<String> serviceActions, ArrayList<String> categories) {
- collectValues(osLibPath + "activity_actions.txt" , activityActions);
- collectValues(osLibPath + "broadcast_actions.txt" , broadcastActions);
- collectValues(osLibPath + "service_actions.txt" , serviceActions);
- collectValues(osLibPath + "categories.txt" , categories);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
+ activityActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
+ broadcastActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
+ serviceActions);
+ collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
+ categories);
}
/**
@@ -400,21 +463,21 @@ public final class FrameworkResourceParser {
* Collects all layout classes information from the class loader and the
* attrs.xml and sets the corresponding structures in the resource manager.
*
- * @param osLibPath The OS path to the SDK tools/lib folder, ending with a separator.
- * @param classLoader The framework SDK jar classloader
+ * @param classLoader The framework SDK jar classloader in case we cannot get the widget from
+ * the platform directly
* @param attrsXmlParser The parser of the attrs.xml file
* @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
* @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
*/
- private void collectLayoutClasses(String osLibPath,
- AndroidJarLoader classLoader,
+ private void collectLayoutClasses(AndroidJarLoader classLoader,
AttrsXmlParser attrsXmlParser,
Collection<ViewClassInfo> mainList, Collection<ViewClassInfo> groupList,
IProgressMonitor monitor) {
LayoutParamsParser ldp = null;
try {
- WidgetListLoader loader = new WidgetListLoader(osLibPath + "widgets.txt");
+ WidgetClassLoader loader = new WidgetClassLoader(
+ mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
if (loader.parseWidgetList(monitor)) {
ldp = new LayoutParamsParser(loader, attrsXmlParser);
}
@@ -465,12 +528,13 @@ public final class FrameworkResourceParser {
}
} catch (NoClassDefFoundError e) {
AdtPlugin.logAndPrintError(e, TAG,
- "Collect preferences failed, class %1$s not found in %2$s", //$NON-NLS-1$
+ "Collect preferences failed, class %1$s not found in %2$s",
e.getMessage(),
classLoader.getSource());
} catch (Throwable e) {
AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
- AdtPlugin.printErrorToConsole("Android Framework Parser", "failed to collect preference classes");
+ AdtPlugin.printErrorToConsole("Android Framework Parser",
+ "failed to collect preference classes");
}
}
@@ -537,40 +601,51 @@ public final class FrameworkResourceParser {
}
/**
- * Returns the URL to the local documentation.
- * Can return null if no documentation is found in the current SDK.
- *
- * @param osDocsPath Path to the documentation folder in the current SDK.
- * The folder may not actually exist.
- * @return A file:// URL on the local documentation folder if it exists or null.
+ * Loads the layout bridge from the dynamically loaded layoutlib.jar
*/
- private String getDocumentationBaseUrl(String osDocsPath) {
- File f = new File(osDocsPath);
+ private LayoutBridge loadLayoutBridge() {
+ LayoutBridge layoutBridge = new LayoutBridge();
- if (f.isDirectory()) {
- try {
- // Note: to create a file:// URL, one would typically use something like
- // f.toURI().toURL().toString(). However this generates a broken path on
- // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
- // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
- // do the correct thing manually.
+ try {
+ // get the URL for the file.
+ File f = new File(mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB));
+ if (f.isFile() == false) {
+ AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
+ } else {
+ URL url = f.toURL();
- String path = f.getAbsolutePath();
- if (File.separatorChar != '/') {
- path = path.replace(File.separatorChar, '/');
+ // create a class loader. Because this jar reference interfaces
+ // that are in the editors plugin, it's important to provide
+ // a parent class loader.
+ layoutBridge.classLoader = new URLClassLoader(new URL[] { url },
+ this.getClass().getClassLoader());
+
+ // load the class
+ Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
+ if (clazz != null) {
+ // instantiate an object of the class.
+ Constructor<?> constructor = clazz.getConstructor();
+ if (constructor != null) {
+ Object bridge = constructor.newInstance();
+ if (bridge instanceof ILayoutBridge) {
+ layoutBridge.bridge = (ILayoutBridge)bridge;
+ }
+ }
}
- // For some reason the URL class doesn't add the mandatory "//" after
- // the "file:" protocol name, so it has to be hacked into the path.
- URL url = new URL("file", null, "//" + path); //$NON-NLS-1$ //$NON-NLS-2$
- String result = url.toString();
- return result;
- } catch (MalformedURLException e) {
- // ignore malformed URLs
+ if (layoutBridge.bridge == null) {
+ layoutBridge.status = LoadStatus.FAILED;
+ AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
+ } else {
+ layoutBridge.status = LoadStatus.LOADED;
+ }
}
+ } catch (Throwable t) {
+ layoutBridge.status = LoadStatus.FAILED;
+ // log the error.
+ AdtPlugin.log(t, "Failed to load the LayoutLib");
}
-
- return null;
+
+ return layoutBridge;
}
-
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
index 19a7de3..f4b10df 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -26,9 +26,9 @@ import java.util.Set;
/**
* Implementation of the {@link IResourceRepository} interface to hold the system resource Ids
- * parsed by {@link FrameworkResourceParser}.
+ * parsed by {@link AndroidTargetParser}.
*/
-public final class FrameworkResourceRepository implements IResourceRepository {
+final class FrameworkResourceRepository implements IResourceRepository {
private Map<ResourceType, List<ResourceItem>> mResourcesMap;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
index f0f48ca..50d319e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
-
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+package com.android.ide.eclipse.adt.sdk;
import java.io.IOException;
import java.util.ArrayList;
@@ -28,7 +26,25 @@ import javax.management.InvalidAttributeValueException;
* Classes which implements this interface provide methods to access framework resource
* data loaded from the SDK.
*/
-public interface IAndroidLoader {
+public interface IAndroidClassLoader {
+
+ /**
+ * Classes which implement this interface provide methods to describe a class.
+ */
+ public interface IClassDescriptor {
+
+ String getCanonicalName();
+
+ IClassDescriptor getSuperclass();
+
+ String getSimpleName();
+
+ IClassDescriptor getEnclosingClass();
+
+ IClassDescriptor[] getDeclaredClasses();
+
+ boolean isInstantiable();
+ }
/**
* Finds and loads all classes that derive from a given set of super classes.
@@ -43,7 +59,7 @@ public interface IAndroidLoader {
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String rootPackage, String[] superClasses)
throws IOException, InvalidAttributeValueException, ClassFormatError;
@@ -52,7 +68,7 @@ public interface IAndroidLoader {
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException;
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException;
/**
* Returns a string indicating the source of the classes, typically for debugging
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
index ee71b60..dc600d7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -52,23 +53,10 @@ import javax.management.InvalidAttributeValueException;
public class LayoutParamsParser {
/**
- * Classes which implement this interface provide methods to describe a class.
+ * Class extending {@link ViewClassInfo} by adding the notion of instantiability.
+ * {@link LayoutParamsParser#getViews()} and {@link LayoutParamsParser#getGroups()} should
+ * only return classes that can be instantiated.
*/
- public interface IClass {
-
- public String getCanonicalName();
-
- public IClass getSuperclass();
-
- public String getSimpleName();
-
- public IClass getEnclosingClass();
-
- public IClass[] getDeclaredClasses();
-
- public boolean isInstantiable();
- }
-
final static class ExtViewClassInfo extends ViewClassInfo {
private boolean mIsInstantiable;
@@ -87,16 +75,16 @@ public class LayoutParamsParser {
/* Note: protected members/methods are overridden in unit tests */
/** Reference to android.view.View */
- protected IClass mTopViewClass;
+ protected IClassDescriptor mTopViewClass;
/** Reference to android.view.ViewGroup */
- protected IClass mTopGroupClass;
+ protected IClassDescriptor mTopGroupClass;
/** Reference to android.view.ViewGroup$LayoutParams */
- protected IClass mTopLayoutParamsClass;
+ protected IClassDescriptor mTopLayoutParamsClass;
/** Input list of all classes deriving from android.view.View */
- protected ArrayList<IClass> mViewList;
+ protected ArrayList<IClassDescriptor> mViewList;
/** Input list of all classes deriving from android.view.ViewGroup */
- protected ArrayList<IClass> mGroupList;
+ protected ArrayList<IClassDescriptor> mGroupList;
/** Output map of FQCN => info on View classes */
protected TreeMap<String, ExtViewClassInfo> mViewMap;
@@ -109,14 +97,14 @@ public class LayoutParamsParser {
protected AttrsXmlParser mAttrsXmlParser;
/** The android.jar class loader */
- protected IAndroidLoader mClassLoader;
+ protected IAndroidClassLoader mClassLoader;
/**
* Instantiate a new LayoutParamsParser.
* @param classLoader The android.jar class loader
* @param attrsXmlParser The parser of the attrs.xml file
*/
- public LayoutParamsParser(IAndroidLoader classLoader,
+ public LayoutParamsParser(IAndroidClassLoader classLoader,
AttrsXmlParser attrsXmlParser) {
mClassLoader = classLoader;
mAttrsXmlParser = attrsXmlParser;
@@ -135,8 +123,8 @@ public class LayoutParamsParser {
/**
* TODO: doc here.
* <p/>
- * Note: on output we should have NO dependency on IClass, otherwise we wouldn't be able
- * to unload the class loader later.
+ * Note: on output we should have NO dependency on {@link IClassDescriptor},
+ * otherwise we wouldn't be able to unload the class loader later.
* <p/>
* Note on Vocabulary: FQCN=Fully Qualified Class Name (e.g. "my.package.class$innerClass")
* @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
@@ -168,8 +156,8 @@ public class LayoutParamsParser {
if (paramsClassName != null) {
superClasses[2] = paramsClassName;
}
- HashMap<String, ArrayList<IClass>> found = mClassLoader.findClassesDerivingFrom(
- "android.", superClasses);
+ HashMap<String, ArrayList<IClassDescriptor>> found =
+ mClassLoader.findClassesDerivingFrom("android.", superClasses);
mTopViewClass = mClassLoader.getClass(rootClassName);
mTopGroupClass = mClassLoader.getClass(groupClassName);
if (paramsClassName != null) {
@@ -196,26 +184,26 @@ public class LayoutParamsParser {
progress.setWorkRemaining(mGroupList.size() + mViewList.size());
- for (IClass groupChild : mGroupList) {
+ for (IClassDescriptor groupChild : mGroupList) {
addGroup(groupChild);
progress.worked(1);
}
- for (IClass viewChild : mViewList) {
+ for (IClassDescriptor viewChild : mViewList) {
if (viewChild != mTopGroupClass) {
addView(viewChild);
}
progress.worked(1);
}
} catch (ClassNotFoundException e) {
- CommonPlugin.log(e, "Problem loading class %1$s or %2$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading class %1$s or %2$s", //$NON-NLS-1$
rootClassName, groupClassName);
} catch (InvalidAttributeValueException e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
} catch (ClassFormatError e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
} catch (IOException e) {
- CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
}
}
@@ -223,7 +211,7 @@ public class LayoutParamsParser {
* Parses a View class and adds a ExtViewClassInfo for it in mViewMap.
* It calls itself recursively to handle super classes which are also Views.
*/
- private ExtViewClassInfo addView(IClass viewClass) {
+ private ExtViewClassInfo addView(IClassDescriptor viewClass) {
String fqcn = viewClass.getCanonicalName();
if (mViewMap.containsKey(fqcn)) {
return mViewMap.get(fqcn);
@@ -238,7 +226,7 @@ public class LayoutParamsParser {
// All view classes derive from mTopViewClass by design.
// Do not lookup the super class for mTopViewClass itself.
if (viewClass.equals(mTopViewClass) == false) {
- IClass superClass = viewClass.getSuperclass();
+ IClassDescriptor superClass = viewClass.getSuperclass();
ExtViewClassInfo superClassInfo = addView(superClass);
info.setSuperClass(superClassInfo);
}
@@ -251,7 +239,7 @@ public class LayoutParamsParser {
* Parses a ViewGroup class and adds a ExtViewClassInfo for it in mGroupMap.
* It calls itself recursively to handle super classes which are also ViewGroups.
*/
- private ExtViewClassInfo addGroup(IClass groupClass) {
+ private ExtViewClassInfo addGroup(IClassDescriptor groupClass) {
String fqcn = groupClass.getCanonicalName();
if (mGroupMap.containsKey(fqcn)) {
return mGroupMap.get(fqcn);
@@ -265,7 +253,7 @@ public class LayoutParamsParser {
// android.view.View (i.e. mTopViewClass here). So the only group that can have View as
// its super class is the ViewGroup base class and we don't try to resolve it since groups
// are loaded before views.
- IClass superClass = groupClass.getSuperclass();
+ IClassDescriptor superClass = groupClass.getSuperclass();
// Assertion: at this point, we should have
// superClass != mTopViewClass || fqcn.equals(AndroidConstants.CLASS_VIEWGROUP);
@@ -291,15 +279,15 @@ public class LayoutParamsParser {
*
* @return The {@link LayoutParamsInfo} for the ViewGroup class or null.
*/
- private LayoutParamsInfo addLayoutParams(IClass groupClass) {
+ private LayoutParamsInfo addLayoutParams(IClassDescriptor groupClass) {
// Is there a LayoutParams in this group class?
- IClass layoutParamsClass = findLayoutParams(groupClass);
+ IClassDescriptor layoutParamsClass = findLayoutParams(groupClass);
// if there's no layout data in the group class, link to the one from the
// super class.
if (layoutParamsClass == null) {
- for (IClass superClass = groupClass.getSuperclass();
+ for (IClassDescriptor superClass = groupClass.getSuperclass();
layoutParamsClass == null &&
superClass != null &&
superClass.equals(mTopViewClass) == false;
@@ -319,7 +307,7 @@ public class LayoutParamsParser {
* Parses a LayoutParams class and returns a LayoutParamsInfo object for it.
* It calls itself recursively to handle the super class of the LayoutParams.
*/
- private LayoutParamsInfo getLayoutParamsInfo(IClass layoutParamsClass) {
+ private LayoutParamsInfo getLayoutParamsInfo(IClassDescriptor layoutParamsClass) {
String fqcn = layoutParamsClass.getCanonicalName();
LayoutParamsInfo layoutParamsInfo = mLayoutParamsMap.get(fqcn);
@@ -330,7 +318,7 @@ public class LayoutParamsParser {
// Find the link on the LayoutParams super class
LayoutParamsInfo superClassInfo = null;
if (layoutParamsClass.equals(mTopLayoutParamsClass) == false) {
- IClass superClass = layoutParamsClass.getSuperclass();
+ IClassDescriptor superClass = layoutParamsClass.getSuperclass();
superClassInfo = getLayoutParamsInfo(superClass);
}
@@ -355,9 +343,9 @@ public class LayoutParamsParser {
* @param groupClass The ViewGroup derived class
* @return The Class of the inner LayoutParams or null if none is declared.
*/
- private IClass findLayoutParams(IClass groupClass) {
- IClass[] innerClasses = groupClass.getDeclaredClasses();
- for (IClass innerClass : innerClasses) {
+ private IClassDescriptor findLayoutParams(IClassDescriptor groupClass) {
+ IClassDescriptor[] innerClasses = groupClass.getDeclaredClasses();
+ for (IClassDescriptor innerClass : innerClasses) {
if (innerClass.getSimpleName().equals(AndroidConstants.CLASS_LAYOUTPARAMS)) {
return innerClass;
}
@@ -365,12 +353,16 @@ public class LayoutParamsParser {
return null;
}
+ /**
+ * Computes and return a list of ViewClassInfo from a map by filtering out the class that
+ * cannot be instantiated.
+ */
private List<ViewClassInfo> getInstantiables(SortedMap<String, ExtViewClassInfo> map) {
Collection<ExtViewClassInfo> values = map.values();
ArrayList<ViewClassInfo> list = new ArrayList<ViewClassInfo>();
for (ExtViewClassInfo info : values) {
- if (info.mIsInstantiable) {
+ if (info.isInstantiable()) {
list.add(info);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
new file mode 100644
index 0000000..6bf0272
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 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.sdk;
+
+/**
+ * Enum for loading status of various SDK parts.
+ */
+public enum LoadStatus {
+ LOADING, LOADED, FAILED;
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
new file mode 100644
index 0000000..3b9d10e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008 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.sdk;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.project.ProjectProperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
+ * at the same time.
+ *
+ * To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
+ * the Sdk object.
+ *
+ * To get the list of platforms present in the SDK, call {@link #getPlatforms()}.
+ * To get the list of add-ons present in the SDK, call {@link #getAddons()}.
+ *
+ */
+public class Sdk {
+ private final static String PROPERTY_PROJECT_TARGET = "androidTarget"; //$NON-NLS-1$
+
+ private static Sdk sCurrentSdk = null;
+
+ private final SdkManager mManager;
+ private final HashMap<IProject, IAndroidTarget> mProjectMap =
+ new HashMap<IProject, IAndroidTarget>();
+ private final HashMap<IAndroidTarget, AndroidTargetData> mTargetMap =
+ new HashMap<IAndroidTarget, AndroidTargetData>();
+ private final String mDocBaseUrl;
+
+ /**
+ * Loads an SDK and returns an {@link Sdk} object if success.
+ * @param sdkLocation the OS path to the SDK.
+ */
+ public static Sdk loadSdk(String sdkLocation) {
+ if (sCurrentSdk != null) {
+ // manual unload?
+ sCurrentSdk = null;
+ }
+
+ final ArrayList<String> logMessages = new ArrayList<String>();
+ ISdkLog log = new ISdkLog() {
+ public void error(String errorFormat, Object... arg) {
+ logMessages.add(String.format(errorFormat, arg));
+ }
+ public void warning(String warningFormat, Object... arg) {
+ logMessages.add(String.format(warningFormat, arg));
+ }
+ };
+
+ // get an SdkManager object for the location
+ SdkManager manager = SdkManager.createManager(sdkLocation, log);
+ if (manager != null) {
+ sCurrentSdk = new Sdk(manager);
+ return sCurrentSdk;
+ } else {
+ StringBuilder sb = new StringBuilder("Error Loading the SDK:\n");
+ for (String msg : logMessages) {
+ sb.append('\n');
+ sb.append(msg);
+ }
+ AdtPlugin.displayError("Android SDK", sb.toString());
+ }
+ return null;
+ }
+
+ /**
+ * Returns the current {@link Sdk} object.
+ */
+ public static Sdk getCurrent() {
+ return sCurrentSdk;
+ }
+
+ /**
+ * Returns the URL to the local documentation.
+ * Can return null if no documentation is found in the current SDK.
+ *
+ * @return A file:// URL on the local documentation folder if it exists or null.
+ */
+ public String getDocumentationBaseUrl() {
+ return mDocBaseUrl;
+ }
+
+ /**
+ * Returns the list of targets that are available in the SDK.
+ */
+ public IAndroidTarget[] getTargets() {
+ return mManager.getTargets();
+ }
+
+ /**
+ * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
+ * @param hash the hash
+ */
+ public IAndroidTarget getTargetFromHashString(String hash) {
+ return mManager.getTargetFromHashString(hash);
+ }
+
+ /**
+ * Associates an {@link IProject} and an {@link IAndroidTarget}.
+ */
+ public void setProject(IProject project, IAndroidTarget target) {
+ synchronized (mProjectMap) {
+ // look for the current target of the project
+ IAndroidTarget previousTarget = mProjectMap.get(project);
+
+ if (target != previousTarget) {
+ // save the target hash string in the project persistent property
+ setProjectTargetHashString(project, target.hashString());
+
+ // put it in a local map for easy access.
+ mProjectMap.put(project, target);
+
+ // recompile the project if needed.
+ IJavaProject javaProject = JavaCore.create(project);
+ AndroidClasspathContainerInitializer.updateProjects(
+ new IJavaProject[] { javaProject });
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}.
+ */
+ public IAndroidTarget getTarget(IProject project) {
+ synchronized (mProjectMap) {
+ IAndroidTarget target = mProjectMap.get(project);
+ if (target == null) {
+ // get the value from the project persistent property.
+ String targetHashString = getProjectTargetHashString(project);
+
+ if (targetHashString != null) {
+ target = mManager.getTargetFromHashString(targetHashString);
+ }
+ }
+
+ return target;
+ }
+ }
+
+ /**
+ * Returns the hash string uniquely identifying the target of a project. This methods reads
+ * the string from the project persistent preferences/properties.
+ * <p/>The string is equivalent to the return of {@link IAndroidTarget#hashString()}.
+ * @param project The project for which to return the target hash string.
+ * @return the hash string or null if the project does not have a target set.
+ */
+ public static String getProjectTargetHashString(IProject project) {
+ // load the default.properties from the project folder.
+ ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+ if (properties == null) {
+ AdtPlugin.log(IStatus.ERROR, "Failed to load properties file for project '%s'",
+ project.getName());
+ return null;
+ }
+
+ return properties.getProperty(ProjectProperties.PROPERTY_TARGET);
+ }
+
+ /**
+ * Sets a target hash string in a project's persistent preferences/property storage.
+ * @param project The project in which to save the hash string.
+ * @param targetHashString The target hash string to save. This must be the result from
+ * {@link IAndroidTarget#hashString()}.
+ */
+ public static void setProjectTargetHashString(IProject project, String targetHashString) {
+ // because we don't want to erase other properties from default.properties, we first load
+ // them
+ ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+ if (properties == null) {
+ // doesn't exist yet? we create it.
+ properties = ProjectProperties.create(project.getLocation().toOSString());
+ }
+
+ // add/change the target hash string.
+ properties.setProperty(ProjectProperties.PROPERTY_TARGET, targetHashString);
+
+ // and rewrite the file.
+ try {
+ properties.save();
+ } catch (IOException e) {
+ AdtPlugin.log(e, "Failed to save default.properties for project '%s'",
+ project.getName());
+ }
+ }
+ /**
+ * Return the {@link PlatformData} for a given {@link IAndroidTarget}.
+ */
+ public AndroidTargetData getTargetData(IAndroidTarget target) {
+ synchronized (mTargetMap) {
+ return mTargetMap.get(target);
+ }
+ }
+
+ private Sdk(SdkManager manager) {
+ mManager = manager;
+
+ // pre-compute some paths
+ mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
+ SdkConstants.OS_SDK_DOCS_FOLDER);
+ }
+
+ void setTargetData(IAndroidTarget target, AndroidTargetData data) {
+ synchronized (mTargetMap) {
+ mTargetMap.put(target, data);
+ }
+ }
+
+ /**
+ * Returns the URL to the local documentation.
+ * Can return null if no documentation is found in the current SDK.
+ *
+ * @param osDocsPath Path to the documentation folder in the current SDK.
+ * The folder may not actually exist.
+ * @return A file:// URL on the local documentation folder if it exists or null.
+ */
+ private String getDocumentationBaseUrl(String osDocsPath) {
+ File f = new File(osDocsPath);
+
+ if (f.isDirectory()) {
+ try {
+ // Note: to create a file:// URL, one would typically use something like
+ // f.toURI().toURL().toString(). However this generates a broken path on
+ // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
+ // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
+ // do the correct thing manually.
+
+ String path = f.getAbsolutePath();
+ if (File.separatorChar != '/') {
+ path = path.replace(File.separatorChar, '/');
+ }
+
+ // For some reason the URL class doesn't add the mandatory "//" after
+ // the "file:" protocol name, so it has to be hacked into the path.
+ URL url = new URL("file", null, "//" + path); //$NON-NLS-1$ //$NON-NLS-2$
+ String result = url.toString();
+ return result;
+ } catch (MalformedURLException e) {
+ // ignore malformed URLs
+ }
+ }
+
+ return null;
+ }
+
+}
+
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
index c85a50e..8db09f2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -42,18 +41,19 @@ import javax.management.InvalidAttributeValueException;
* where code is a single letter (W for widget, L for layout, P for layout params), and class names
* are the fully qualified name of the classes.
*/
-public final class WidgetListLoader implements IAndroidLoader {
+public final class WidgetClassLoader implements IAndroidClassLoader {
/**
* Basic class containing the class descriptions found in the text file.
*/
- private final static class ClassDescriptor implements IClass {
+ private final static class ClassDescriptor implements IClassDescriptor {
private String mName;
private String mSimpleName;
private ClassDescriptor mSuperClass;
private ClassDescriptor mEnclosingClass;
- private final ArrayList<IClass> mDeclaredClasses = new ArrayList<IClass>();
+ private final ArrayList<IClassDescriptor> mDeclaredClasses =
+ new ArrayList<IClassDescriptor>();
private boolean mIsInstantiable = false;
ClassDescriptor(String fqcn) {
@@ -69,15 +69,15 @@ public final class WidgetListLoader implements IAndroidLoader {
return mSimpleName;
}
- public IClass[] getDeclaredClasses() {
- return mDeclaredClasses.toArray(new IClass[mDeclaredClasses.size()]);
+ public IClassDescriptor[] getDeclaredClasses() {
+ return mDeclaredClasses.toArray(new IClassDescriptor[mDeclaredClasses.size()]);
}
private void addDeclaredClass(ClassDescriptor declaredClass) {
mDeclaredClasses.add(declaredClass);
}
- public IClass getEnclosingClass() {
+ public IClassDescriptor getEnclosingClass() {
return mEnclosingClass;
}
@@ -93,7 +93,7 @@ public final class WidgetListLoader implements IAndroidLoader {
mName = enclosingClass.mName + "$" + mName.substring(enclosingClass.mName.length() + 1);
}
- public IClass getSuperclass() {
+ public IClassDescriptor getSuperclass() {
return mSuperClass;
}
@@ -147,7 +147,7 @@ public final class WidgetListLoader implements IAndroidLoader {
* @param osFilePath the OS path of the file to load.
* @throws FileNotFoundException if the file is not found.
*/
- WidgetListLoader(String osFilePath) throws FileNotFoundException {
+ WidgetClassLoader(String osFilePath) throws FileNotFoundException {
mOsFilePath = osFilePath;
mReader = new BufferedReader(new FileReader(osFilePath));
}
@@ -301,20 +301,21 @@ public final class WidgetListLoader implements IAndroidLoader {
* @throws InvalidAttributeValueException
* @throws ClassFormatError
*/
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(String rootPackage,
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(String rootPackage,
String[] superClasses) throws IOException, InvalidAttributeValueException,
ClassFormatError {
- HashMap<String, ArrayList<IClass>> map = new HashMap<String, ArrayList<IClass>>();
+ HashMap<String, ArrayList<IClassDescriptor>> map =
+ new HashMap<String, ArrayList<IClassDescriptor>>();
- ArrayList<IClass> list = new ArrayList<IClass>();
+ ArrayList<IClassDescriptor> list = new ArrayList<IClassDescriptor>();
list.addAll(mWidgetMap.values());
map.put(AndroidConstants.CLASS_VIEW, list);
- list = new ArrayList<IClass>();
+ list = new ArrayList<IClassDescriptor>();
list.addAll(mLayoutMap.values());
map.put(AndroidConstants.CLASS_VIEWGROUP, list);
- list = new ArrayList<IClass>();
+ list = new ArrayList<IClassDescriptor>();
list.addAll(mLayoutParamsMap.values());
map.put(AndroidConstants.CLASS_VIEWGROUP_LAYOUTPARAMS, list);
@@ -326,7 +327,7 @@ public final class WidgetListLoader implements IAndroidLoader {
* @param className the fully-qualified name of the class to return.
* @throws ClassNotFoundException
*/
- public IClass getClass(String className) throws ClassNotFoundException {
+ public IClassDescriptor getClass(String className) throws ClassNotFoundException {
return mMap.get(className);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
index d395905..8044bcb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
@@ -20,11 +20,13 @@
* org.eclipse.jdt.internal.ui.wizards.JavaProjectWizardFirstPage
*/
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
-import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IProject;
@@ -120,6 +122,7 @@ public class NewProjectCreationPage extends WizardPage {
private boolean mInternalActivityNameUpdate;
protected boolean mProjectNameModifiedByUser;
protected boolean mApplicationNameModifiedByUser;
+ private SdkTargetSelector mSdkTargetSelector;
/**
@@ -133,7 +136,9 @@ public class NewProjectCreationPage extends WizardPage {
if (sCustomLocationOsPath == null ||
sCustomLocationOsPath.length() == 0 ||
!new File(sCustomLocationOsPath).isDirectory()) {
- sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+ // FIXME location of samples is pretty much impossible here.
+ //sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+ sCustomLocationOsPath = File.listRoots()[0].getAbsolutePath();
}
}
@@ -200,6 +205,11 @@ public class NewProjectCreationPage extends WizardPage {
return mSourceFolder;
}
}
+
+ /** Returns the current sdk target or null if none has been selected yet. */
+ public IAndroidTarget getSdkTarget() {
+ return mSdkTargetSelector == null ? null : mSdkTargetSelector.getFirstSelected();
+ }
/**
* Overrides @DialogPage.setVisible(boolean) to put the focus in the project name when
@@ -232,15 +242,19 @@ public class NewProjectCreationPage extends WizardPage {
createProjectNameGroup(composite);
createLocationGroup(composite);
+ createTargetGroup(composite);
createPropertiesGroup(composite);
// Update state the first time
enableLocationWidgets();
- setPageComplete(validatePage());
+
// Show description the first time
setErrorMessage(null);
setMessage(null);
setControl(composite);
+
+ // Validate. This will complain about the first empty field.
+ setPageComplete(validatePage());
}
/**
@@ -357,6 +371,33 @@ public class NewProjectCreationPage extends WizardPage {
}
/**
+ * Creates the target group.
+ * It only contains an SdkTargetSelector.
+ */
+ private void createTargetGroup(Composite parent) {
+ Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ // Layout has 1 column
+ group.setLayout(new GridLayout());
+ group.setLayoutData(new GridData(GridData.FILL_BOTH));
+ group.setFont(parent.getFont());
+ group.setText("Target");
+
+ // get the targets from the sdk
+ IAndroidTarget[] targets = null;
+ if (Sdk.getCurrent() != null) {
+ targets = Sdk.getCurrent().getTargets();
+ }
+
+ mSdkTargetSelector = new SdkTargetSelector(group, targets, false /*multi-selection*/);
+ mSdkTargetSelector.setSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setPageComplete(validatePage());
+ }
+ });
+ }
+
+ /**
* Display a directory browser and update the location path field with the selected path
*/
private void openDirectoryBrowser() {
@@ -755,6 +796,9 @@ public class NewProjectCreationPage extends WizardPage {
status |= validateLocationPath(workspace);
}
if ((status & MSG_ERROR) == 0) {
+ status |= validateSdkTarget();
+ }
+ if ((status & MSG_ERROR) == 0) {
status |= validatePackageField();
}
if ((status & MSG_ERROR) == 0) {
@@ -894,6 +938,18 @@ public class NewProjectCreationPage extends WizardPage {
}
/**
+ * Validates the sdk target choice.
+ *
+ * @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
+ */
+ private int validateSdkTarget() {
+ if (getSdkTarget() == null) {
+ return setStatus("An SDK Target must be specified.", MSG_ERROR);
+ }
+ return MSG_NONE;
+ }
+
+ /**
* Validates the activity name field.
*
* @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
index a67f5ed..a582217 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.project.AndroidNature;
import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -60,6 +62,7 @@ import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
/**
* A "New Android Project" Wizard.
@@ -81,6 +84,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
private static final String PARAM_STRING_CONTENT = "STRING_CONTENT"; //$NON-NLS-1$
private static final String PARAM_IS_NEW_PROJECT = "IS_NEW_PROJECT"; //$NON-NLS-1$
private static final String PARAM_SRC_FOLDER = "SRC_FOLDER"; //$NON-NLS-1$
+ private static final String PARAM_SDK_TARGET = "SDK_TARGET"; //$NON-NLS-1$
private static final String PH_ACTIVITIES = "ACTIVITIES"; //$NON-NLS-1$
private static final String PH_INTENT_FILTERS = "INTENT_FILTERS"; //$NON-NLS-1$
@@ -223,13 +227,14 @@ public class NewProjectWizard extends Wizard implements INewWizard {
final IProject project = workspace.getRoot().getProject(mMainPage.getProjectName());
final IProjectDescription description = workspace.newProjectDescription(project.getName());
- final Map<String, String> parameters = new HashMap<String, String>();
+ final Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(PARAM_PROJECT, mMainPage.getProjectName());
parameters.put(PARAM_PACKAGE, mMainPage.getPackageName());
parameters.put(PARAM_APPLICATION, STRING_RSRC_PREFIX + STRING_APP_NAME);
parameters.put(PARAM_SDK_TOOLS_DIR, AdtPlugin.getOsSdkToolsFolder());
- parameters.put(PARAM_IS_NEW_PROJECT, Boolean.toString(mMainPage.isNewProject()));
+ parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
+ parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
if (mMainPage.isCreateActivity()) {
// An activity name can be of the form ".package.Class" or ".Class".
@@ -315,7 +320,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
* to create or modify the project or if it is canceled by the user.
*/
private void createProjectAsync(IProject project, IProjectDescription description,
- IProgressMonitor monitor, Map<String, String> parameters,
+ IProgressMonitor monitor, Map<String, Object> parameters,
Map<String, String> stringDictionary)
throws InvocationTargetException {
monitor.beginTask("Create Android Project", 100);
@@ -330,7 +335,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
// Create folders in the project if they don't already exist
addDefaultDirectories(project, AndroidConstants.WS_ROOT, DEFAULT_DIRECTORIES, monitor);
- String[] sourceFolder = new String[] { parameters.get(PARAM_SRC_FOLDER) };
+ String[] sourceFolder = new String[] { (String) parameters.get(PARAM_SRC_FOLDER) };
addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolder, monitor);
// Create the resource folders in the project if they don't already exist.
@@ -340,7 +345,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
IJavaProject javaProject = JavaCore.create(project);
setupSourceFolder(javaProject, sourceFolder[0], monitor);
- if (Boolean.parseBoolean(parameters.get(PARAM_IS_NEW_PROJECT))) {
+ if (((Boolean) parameters.get(PARAM_IS_NEW_PROJECT)).booleanValue()) {
// Create files in the project if they don't already exist
addManifest(project, parameters, stringDictionary, monitor);
@@ -360,6 +365,8 @@ public class NewProjectWizard extends Wizard implements INewWizard {
monitor);
}
+ Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET));
+
// Fix the project to make sure all properties are as expected.
// Necessary for existing projects and good for new ones to.
ProjectHelper.fixProject(project);
@@ -409,7 +416,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
* @throws IOException if the method fails to create the files in the
* project.
*/
- private void addManifest(IProject project, Map<String, String> parameters,
+ private void addManifest(IProject project, Map<String, Object> parameters,
Map<String, String> stringDictionary, IProgressMonitor monitor)
throws CoreException, IOException {
@@ -543,16 +550,16 @@ public class NewProjectWizard extends Wizard implements INewWizard {
* project.
*/
private void addSampleCode(IProject project, String sourceFolder,
- Map<String, String> parameters, Map<String, String> stringDictionary,
+ Map<String, Object> parameters, Map<String, String> stringDictionary,
IProgressMonitor monitor) throws CoreException, IOException {
// create the java package directories.
IFolder pkgFolder = project.getFolder(sourceFolder);
- String packageName = parameters.get(PARAM_PACKAGE);
+ String packageName = (String) parameters.get(PARAM_PACKAGE);
// The PARAM_ACTIVITY key will be absent if no activity should be created,
// in which case activityName will be null.
- String activityName = parameters.get(PARAM_ACTIVITY);
- Map<String, String> java_activity_parameters = parameters;
+ String activityName = (String) parameters.get(PARAM_ACTIVITY);
+ Map<String, Object> java_activity_parameters = parameters;
if (activityName != null) {
if (activityName.indexOf('.') >= 0) {
// There are package names in the activity name. Transform packageName to add
@@ -564,7 +571,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
// Also update the values used in the JAVA_FILE_TEMPLATE below
// (but not the ones from the manifest so don't change the caller's dictionary)
- java_activity_parameters = new HashMap<String, String>(parameters);
+ java_activity_parameters = new HashMap<String, Object>(parameters);
java_activity_parameters.put(PARAM_PACKAGE, packageName);
java_activity_parameters.put(PARAM_ACTIVITY, activityName);
}
@@ -665,7 +672,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
* length.
*/
private void copyFile(String resourceFilename, IFile destFile,
- Map<String, String> parameters, IProgressMonitor monitor)
+ Map<String, Object> parameters, IProgressMonitor monitor)
throws CoreException, IOException {
// Read existing file.
@@ -692,13 +699,14 @@ public class NewProjectWizard extends Wizard implements INewWizard {
* Replaces placeholders found in a string with values.
*
* @param str the string to search for placeholders.
- * @param parameters a map of <placeholder, Value> to search for in the
- * string
+ * @param parameters a map of <placeholder, Value> to search for in the string
* @return A new String object with the placeholder replaced by the values.
*/
- private String replaceParameters(String str, Map<String, String> parameters) {
- for (String key : parameters.keySet()) {
- str = str.replaceAll(key, parameters.get(key));
+ private String replaceParameters(String str, Map<String, Object> parameters) {
+ for (Entry<String, Object> entry : parameters.entrySet()) {
+ if (entry.getValue() instanceof String) {
+ str = str.replaceAll(entry.getKey(), (String) entry.getValue());
+ }
}
return str;
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
index 02cef2d..f3f7b79 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.common;
+import com.android.sdklib.SdkConstants;
+
import java.io.File;
/**
@@ -38,8 +40,11 @@ import java.io.File;
*
*/
public class AndroidConstants {
- /** The Editors Plugin ID */
- public static final String EDITORS_PLUGIN_ID = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
+ /**
+ * The old Editors Plugin ID. It is still used in some places for compatibility.
+ * Please do not use for new features.
+ */
+ public static final String EDITORS_NAMESPACE = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
/** Nature of android projects */
public final static String NATURE = "com.android.ide.eclipse.adt.AndroidNature"; //$NON-NLS-1$
@@ -72,6 +77,8 @@ public class AndroidConstants {
public final static String EXT_JAR = "jar"; //$NON-NLS-1$
/** Extension of aidl files, i.e. "aidl" */
public final static String EXT_AIDL = "aidl"; //$NON-NLS-1$
+ /** Extension of native libraries, i.e. "so" */
+ public final static String EXT_NATIVE_LIB = "so"; //$NON-NLS-1$
private final static String DOT = "."; //$NON-NLS-1$
@@ -90,17 +97,8 @@ public class AndroidConstants {
/** Name of the manifest file, i.e. "AndroidManifest.xml". */
public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$
+ public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$
- /** Name of the framework library, i.e. "android.jar" */
- public static final String FN_FRAMEWORK_LIBRARY = "android.jar"; //$NON-NLS-1$
- /** Name of the layout attributes, i.e. "attrs.xml" */
- public static final String FN_ATTRS_XML = "attrs.xml"; //$NON-NLS-1$
- /** Name of the layout attributes, i.e. "attrs_manifest.xml" */
- public static final String FN_ATTRS_MANIFEST_XML = "attrs_manifest.xml"; //$NON-NLS-1$
- /** framework aidl import file */
- public static final String FN_FRAMEWORK_AIDL = "framework.aidl"; //$NON-NLS-1$
- /** layoutlib.jar file */
- public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar"; //$NON-NLS-1$
/** dex.jar file */
public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$
/** Name of the android sources directory */
@@ -116,10 +114,6 @@ public class AndroidConstants {
public final static String FN_CLASSES_DEX = "classes.dex"; //$NON-NLS-1$
/** Temporary packaged resources file name, i.e. "resources.ap_" */
public final static String FN_RESOURCES_AP_ = "resources.ap_"; //$NON-NLS-1$
- /** build properties file */
- public final static String FN_BUILD_PROP = "build.prop"; //$NON-NLS-1$
- /** plugin properties file */
- public final static String FN_PLUGIN_PROP = "plugin.prop"; //$NON-NLS-1$
public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
"adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -136,15 +130,21 @@ public class AndroidConstants {
public final static String FN_TRACEVIEW = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
"traceview.exe" : "traceview"; //$NON-NLS-1$ //$NON-NLS-2$
- /** Skin layout file */
- public final static String FN_LAYOUT = "layout";//$NON-NLS-1$
+ /** Folder Names for Android Projects . */
- /** Resources folder name, i.e. "res". */
+ /* Resources folder name, i.e. "res". */
public final static String FD_RESOURCES = "res"; //$NON-NLS-1$
/** Assets folder name, i.e. "assets" */
public final static String FD_ASSETS = "assets"; //$NON-NLS-1$
/** Default source folder name, i.e. "src" */
public final static String FD_SOURCES = "src"; //$NON-NLS-1$
+ /** Default native library folder name inside the project, i.e. "libs"
+ * While the folder inside the .apk is "lib", we call that one libs because
+ * that's what we use in ant for both .jar and .so and we need to make the 2 development ways
+ * compatible. */
+ public final static String FD_NATIVE_LIBS = "libs"; //$NON-NLS-1$
+ /** Native lib folder inside the APK: "lib" */
+ public final static String FD_APK_NATIVE_LIBS = "lib"; //$NON-NLS-1$
/** Default bin folder name, i.e. "bin" */
public final static String FD_BINARIES = "bin"; //$NON-NLS-1$
/** Default anim resource folder name, i.e. "anim" */
@@ -163,22 +163,6 @@ public class AndroidConstants {
public final static String FD_XML = "xml"; //$NON-NLS-1$
/** Default raw resource folder name, i.e. "raw" */
public final static String FD_RAW = "raw"; //$NON-NLS-1$
- /** Name of the tools folder. */
- public final static String FD_TOOLS = "tools"; //$NON-NLS-1$
- /** Name of the libs folder. */
- public final static String FD_LIBS = "lib"; //$NON-NLS-1$
- /** Name of the docs folder. */
- public final static String FD_DOCS = "docs"; //$NON-NLS-1$
- /** Name of the images folder. */
- public final static String FD_IMAGES = "images"; //$NON-NLS-1$
- /** Name of the skins folder. */
- public final static String FD_SKINS = "skins"; //$NON-NLS-1$
- /** Name of the samples folder. */
- public final static String FD_SAMPLES = "samples"; //$NON-NLS-1$
- /** Name of the folder containing the default framework resources. */
- public final static String FD_DEFAULT_RES = "default"; //$NON-NLS-1$
- /** SDK font folder name, i.e. "fonts" */
- public final static String FD_FONTS = "fonts"; //$NON-NLS-1$
/** Absolute path of the workspace root, i.e. "/" */
public final static String WS_ROOT = WS_SEP;
@@ -190,57 +174,16 @@ public class AndroidConstants {
public final static String WS_ASSETS = WS_SEP + FD_ASSETS;
/** Leaf of the javaDoc folder. Does not start with a separator. */
- public final static String WS_JAVADOC_FOLDER_LEAF = FD_DOCS + "/reference"; //$NON-NLS-1$
-
- /** Path of the documentation directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_DOCS_FOLDER = FD_DOCS + File.separator;
-
- /** Path of the tools directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_TOOLS_FOLDER = FD_TOOLS + File.separator;
+ public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/reference"; //$NON-NLS-1$
/** Path of the samples directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_SAMPLES_FOLDER = FD_SAMPLES + File.separator;
-
- /** Path of the lib directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_LIBS_FOLDER =
- OS_SDK_TOOLS_FOLDER + FD_LIBS + File.separator;
-
- /** Path of the resources directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_RESOURCES_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_RESOURCES + File.separator;
-
- /** Path of the resources directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_FONTS_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_FONTS + File.separator;
-
- /** Path of the skin directory relative to the sdk folder.
- * This is an OS path, ending with a separator. */
- public final static String OS_SDK_SKINS_FOLDER =
- OS_SDK_LIBS_FOLDER + FD_IMAGES + File.separator + FD_SKINS + File.separator;
-
- /** Path of the attrs.xml file relative to the sdk folder. */
- public final static String OS_SDK_ATTRS_XML =
- OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
- FD_VALUES + File.separator + FN_ATTRS_XML;
-
- /** Path of the attrs_manifest.xml file relative to the sdk folder. */
- public final static String OS_SDK_ATTRS_MANIFEST_XML =
- OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
- FD_VALUES + File.separator + FN_ATTRS_MANIFEST_XML;
-
- /** Path of the layoutlib.jar file relative to the sdk folder. */
- public final static String OS_SDK_LIBS_LAYOUTLIB_JAR =
- OS_SDK_LIBS_FOLDER + FN_LAYOUTLIB_JAR;
+ * This is an OS path, ending with a separator.
+ * FIXME: remove once the NPW is fixed. */
+ public final static String OS_SDK_SAMPLES_FOLDER = SdkConstants.FD_SAMPLES + File.separator;
/** Path of the dx.jar file relative to the sdk folder. */
public final static String OS_SDK_LIBS_DX_JAR =
- OS_SDK_LIBS_FOLDER + FN_DX_JAR;
+ SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + FN_DX_JAR;
/** Regexp for single dot */
public final static String RE_DOT = "\\."; //$NON-NLS-1$
@@ -255,17 +198,20 @@ public class AndroidConstants {
/** Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s" */
public final static String NS_CUSTOM_RESOURCES = "http://schemas.android.com/apk/res/%1$s"; //$NON-NLS-1$
+ /** The old common plug-in ID. Please do not use for new features. */
+ public static final String COMMON_PLUGIN_ID = "com.android.ide.eclipse.common"; //$NON-NLS-1$
+
/** aapt marker error. */
- public final static String MARKER_AAPT = CommonPlugin.PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
+ public final static String MARKER_AAPT = COMMON_PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
/** XML marker error. */
- public final static String MARKER_XML = CommonPlugin.PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
+ public final static String MARKER_XML = COMMON_PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
/** aidl marker error. */
- public final static String MARKER_AIDL = CommonPlugin.PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
+ public final static String MARKER_AIDL = COMMON_PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
/** android marker error */
- public final static String MARKER_ANDROID = CommonPlugin.PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
+ public final static String MARKER_ANDROID = COMMON_PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
/** Name for the "type" marker attribute */
public final static String MARKER_ATTR_TYPE = "android.type"; //$NON-NLS-1$
@@ -301,6 +247,7 @@ public class AndroidConstants {
public final static String CLASS_PREFERENCES =
"android.preference." + CLASS_PREFERENCE_SCREEN; //$NON-NLS-1$
public final static String CLASS_PREFERENCEGROUP = "android.preference.PreferenceGroup"; //$NON-NLS-1$
+ public final static String CLASS_PARCELABLE = "android.os.Parcelable"; //$NON-NLS-1$
public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
index 8dd8e60..6dc8562 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
@@ -53,7 +53,7 @@ public final class EclipseUiHelper {
try {
IViewPart part = page.showView(viewId,
null /* secondaryId */,
- activate ? page.VIEW_ACTIVATE : page.VIEW_VISIBLE);
+ activate ? IWorkbenchPage.VIEW_ACTIVATE : IWorkbenchPage.VIEW_VISIBLE);
} catch (PartInitException e) {
// ignore
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
index 3f1bde4..3f1bde4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
index 345c663..345c663 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
index 6ccf4f2..6ccf4f2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
index dba6edc..dba6edc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
index 58c2f40..58c2f40 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
index 2db9e9b..2db9e9b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index 42f2a8b..cb98525 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -44,6 +44,7 @@ public class AndroidManifestParser {
private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
+ private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -53,6 +54,7 @@ public class AndroidManifestParser {
private final static String NODE_INTENT = "intent-filter"; //$NON-NLS-1$
private final static String NODE_ACTION = "action"; //$NON-NLS-1$
private final static String NODE_CATEGORY = "category"; //$NON-NLS-1$
+ private final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$
private final static int LEVEL_MANIFEST = 0;
private final static int LEVEL_APPLICATION = 1;
@@ -77,6 +79,8 @@ public class AndroidManifestParser {
private Set<String> mProcesses = null;
/** debuggable attribute value. If null, the attribute is not present. */
private Boolean mDebuggable = null;
+ /** API level requirement. if 0 the attribute was not present. */
+ private int mApiLevelRequirement = 0;
//--- temporary data/flags used during parsing
private IJavaProject mJavaProject;
@@ -142,12 +146,19 @@ public class AndroidManifestParser {
}
/**
- * Returns the debuggable attribute value or null if it is not set.
+ * Returns the <code>debuggable</code> attribute value or null if it is not set.
*/
Boolean getDebuggable() {
return mDebuggable;
}
+ /**
+ * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set.
+ */
+ int getApiLevelRequirement() {
+ return mApiLevelRequirement;
+ }
+
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
*/
@@ -171,7 +182,7 @@ public class AndroidManifestParser {
// if we're at a valid level
if (mValidLevel == mCurrentLevel) {
- String processName;
+ String value;
switch (mValidLevel) {
case LEVEL_MANIFEST:
if (NODE_MANIFEST.equals(localName)) {
@@ -183,19 +194,28 @@ public class AndroidManifestParser {
break;
case LEVEL_APPLICATION:
if (NODE_APPLICATION.equals(localName)) {
- processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+ value = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
true /* hasNamespace */);
- if (processName != null) {
- addProcessName(processName);
+ if (value != null) {
+ addProcessName(value);
}
- String debuggable = getAttributeValue(attributes,
- ATTRIBUTE_DEBUGGABLE, true /* hasNamespace*/);
- if (debuggable != null) {
- mDebuggable = Boolean.parseBoolean(debuggable);
+ value = getAttributeValue(attributes, ATTRIBUTE_DEBUGGABLE,
+ true /* hasNamespace*/);
+ if (value != null) {
+ mDebuggable = Boolean.parseBoolean(value);
}
mValidLevel++;
+ } else if (NODE_USES_SDK.equals(localName)) {
+ value = getAttributeValue(attributes, ATTRIBUTE_MIN_SDK_VERSION,
+ true /* hasNamespace */);
+
+ try {
+ mApiLevelRequirement = Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ handleError(e, -1 /* lineNumber */);
+ }
}
break;
case LEVEL_ACTIVITY:
@@ -301,7 +321,7 @@ public class AndroidManifestParser {
@Override
public void error(SAXParseException e) throws SAXException {
if (mMarkErrors) {
- super.error(e);
+ handleError(e, e.getLineNumber());
}
}
@@ -311,7 +331,7 @@ public class AndroidManifestParser {
@Override
public void fatalError(SAXParseException e) throws SAXException {
if (mMarkErrors) {
- super.fatalError(e);
+ handleError(e, e.getLineNumber());
}
}
@@ -457,6 +477,7 @@ public class AndroidManifestParser {
private final String mLauncherActivity;
private final String[] mProcesses;
private final Boolean mDebuggable;
+ private final int mApiLevelRequirement;
static {
sParserFactory = SAXParserFactory.newInstance();
@@ -491,7 +512,8 @@ public class AndroidManifestParser {
return new AndroidManifestParser(manifestHandler.getPackage(),
manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
- manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+ manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+ manifestHandler.getApiLevelRequirement());
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
} catch (IOException e) {
@@ -530,7 +552,8 @@ public class AndroidManifestParser {
// get the result from the handler
return new AndroidManifestParser(manifestHandler.getPackage(),
manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
- manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+ manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+ manifestHandler.getApiLevelRequirement());
}
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
@@ -610,6 +633,14 @@ public class AndroidManifestParser {
}
/**
+ * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set.
+ */
+ public int getApiLevelRequirement() {
+ return mApiLevelRequirement;
+ }
+
+
+ /**
* Private constructor to enforce using
* {@link #parse(IJavaProject, XmlErrorListener, boolean, boolean)},
* {@link #parse(IJavaProject, IFile, XmlErrorListener, boolean, boolean)},
@@ -619,14 +650,17 @@ public class AndroidManifestParser {
* @param activities the list of activities parsed from the manifest.
* @param launcherActivity the launcher activity parser from the manifest.
* @param processes the list of custom processes declared in the manifest.
- * @param debuggable the debuggable attribute.
+ * @param debuggable the debuggable attribute, or null if not set.
+ * @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set.
*/
private AndroidManifestParser(String javaPackage, String[] activities,
- String launcherActivity, String[] processes, Boolean debuggable) {
+ String launcherActivity, String[] processes, Boolean debuggable,
+ int apiLevelRequirement) {
mJavaPackage = javaPackage;
mActivities = activities;
mLauncherActivity = launcherActivity;
mProcesses = processes;
mDebuggable = debuggable;
+ mApiLevelRequirement = apiLevelRequirement;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
index 530c89e..530c89e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
index 57ca496..c69e875 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.common.project;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
import org.eclipse.core.resources.IFile;
@@ -108,7 +108,7 @@ public final class BaseProjectHelper {
return marker;
} catch (CoreException e) {
- CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+ AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
markerId, file.getFullPath());
}
@@ -117,10 +117,9 @@ public final class BaseProjectHelper {
/**
* Adds a marker to a resource.
- * @param file the file to be marked
+ * @param resource the file to be marked
* @param markerId The id of the marker to add.
* @param message the message associated with the mark
- * @param lineNumber the line number where to put the mark
* @param severity the severity of the marker.
* @return the IMarker that was added or null if it failed to add one.
*/
@@ -138,7 +137,7 @@ public final class BaseProjectHelper {
return marker;
} catch (CoreException e) {
- CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+ AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
markerId, resource.getFullPath());
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
index 4b169a1..4b169a1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
index 0c43499..0c43499 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
index 3492cb4..26fbf42 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
@@ -65,11 +65,7 @@ public class XmlErrorHandler extends DefaultHandler {
*/
@Override
public void error(SAXParseException exception) throws SAXException {
- if (mErrorListener != null) {
- mErrorListener.errorFound();
- }
- BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
- exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+ handleError(exception, exception.getLineNumber());
}
/**
@@ -77,13 +73,8 @@ public class XmlErrorHandler extends DefaultHandler {
* @param exception the parsing exception
*/
@Override
- public void fatalError(SAXParseException exception)
- throws SAXException {
- if (mErrorListener != null) {
- mErrorListener.errorFound();
- }
- BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
- exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+ public void fatalError(SAXParseException exception) throws SAXException {
+ handleError(exception, exception.getLineNumber());
}
/**
@@ -99,4 +90,23 @@ public class XmlErrorHandler extends DefaultHandler {
protected final IFile getFile() {
return mFile;
}
+
+ /**
+ * Handles a parsing error and an optional line number.
+ * @param exception
+ * @param lineNumber
+ */
+ protected void handleError(Exception exception, int lineNumber) {
+ if (mErrorListener != null) {
+ mErrorListener.errorFound();
+ }
+
+ if (lineNumber != -1) {
+ BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+ lineNumber, IMarker.SEVERITY_ERROR);
+ } else {
+ BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+ IMarker.SEVERITY_ERROR);
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
index 43260c0..3176c8e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.common.resources;
-import com.android.ide.eclipse.common.CommonPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -106,7 +106,7 @@ public final class AttrsXmlParser {
Document doc = getDocument();
if (doc == null) {
- CommonPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
@@ -119,7 +119,7 @@ public final class AttrsXmlParser {
}
if (res == null) {
- CommonPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
return this;
}
@@ -189,13 +189,13 @@ public final class AttrsXmlParser {
DocumentBuilder builder = factory.newDocumentBuilder();
mDocument = builder.parse(new File(mOsAttrsXmlPath));
} catch (ParserConfigurationException e) {
- CommonPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (SAXException e) {
- CommonPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
} catch (IOException e) {
- CommonPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
mOsAttrsXmlPath);
}
}
@@ -340,7 +340,7 @@ public final class AttrsXmlParser {
formats.add(format);
}
} catch (IllegalArgumentException e) {
- CommonPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
+ AdtPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
f, name, getOsAttrsXmlPath());
}
}
@@ -389,7 +389,7 @@ public final class AttrsXmlParser {
if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(filter)) {
Node nameNode = child.getAttributes().getNamedItem("name"); //$NON-NLS-1$
if (nameNode == null) {
- CommonPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Missing name attribute in <attr name=\"%s\"><%s></attr>", //$NON-NLS-1$
attrName, filter);
} else {
@@ -401,7 +401,7 @@ public final class AttrsXmlParser {
Node valueNode = child.getAttributes().getNamedItem("value"); //$NON-NLS-1$
if (valueNode == null) {
- CommonPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Missing value attribute in <attr name=\"%s\"><%s name=\"%s\"></attr>", //$NON-NLS-1$
attrName, filter, name);
} else {
@@ -419,7 +419,7 @@ public final class AttrsXmlParser {
map.put(name, Integer.valueOf(i));
} catch(NumberFormatException e) {
- CommonPlugin.log(e,
+ AdtPlugin.log(e,
"Value in <attr name=\"%s\"><%s name=\"%s\" value=\"%s\"></attr> is not a valid decimal or hexadecimal", //$NON-NLS-1$
attrName, filter, name, value);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
index 6cff62c..6cff62c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
index 38b7e03..38b7e03 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
index 53d9077..53d9077 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
index 3819997..3819997 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
index 83527f3..83527f3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
index 3d64e5d..60c471e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
@@ -21,7 +21,7 @@ package com.android.ide.eclipse.common.resources;
*/
public enum ResourceType {
ANIM("anim", "Animation"), //$NON-NLS-1$
- ARRAY("array", "Array"), //$NON-NLS-1$
+ ARRAY("array", "Array", "string-array", "integer-array"), //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
ATTR("attr", "Attr"), //$NON-NLS-1$
COLOR("color", "Color"), //$NON-NLS-1$
DIMEN("dimen", "Dimension"), //$NON-NLS-1$
@@ -35,12 +35,14 @@ public enum ResourceType {
STYLEABLE("styleable", "Styleable"), //$NON-NLS-1$
XML("xml", "XML"); //$NON-NLS-1$
- private String mName;
- private String mDisplayName;
+ private final String mName;
+ private final String mDisplayName;
+ private final String[] mAlternateXmlNames;
- ResourceType(String name, String displayName) {
+ ResourceType(String name, String displayName, String... alternateXmlNames) {
mName = name;
mDisplayName = displayName;
+ mAlternateXmlNames = alternateXmlNames;
}
/**
@@ -66,6 +68,13 @@ public enum ResourceType {
for (ResourceType rType : values()) {
if (rType.mName.equals(name)) {
return rType;
+ } else if (rType.mAlternateXmlNames != null) {
+ // if there are alternate Xml Names, we test those too
+ for (String alternate : rType.mAlternateXmlNames) {
+ if (alternate.equals(name)) {
+ return rType;
+ }
+ }
}
}
return null;
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
index 619e3cc..619e3cc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
index 1dd0c27..d1b4547 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
@@ -16,11 +16,12 @@
package com.android.ide.eclipse.editors;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
@@ -80,15 +81,20 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
protected final static String ROOT_ELEMENT = "";
/** Descriptor of the root of the XML hierarchy. This a "fake" ElementDescriptor which
- * is used to list all the possible roots given by actual implementations. */
+ * is used to list all the possible roots given by actual implementations.
+ * DO NOT USE DIRECTLY. Call {@link #getRootDescriptor()} instead. */
private ElementDescriptor mRootDescriptor;
+ private final int mDescriptorId;
+
+ private AndroidEditor mEditor;
+
/**
* Constructor for AndroidContentAssist
* @param rootElementDescriptors The valid root elements of the XML hierarchy
*/
- public AndroidContentAssist(ElementDescriptor[] rootElementDescriptors) {
- mRootDescriptor = new ElementDescriptor("", rootElementDescriptors);
+ public AndroidContentAssist(int descriptorId) {
+ mDescriptorId = descriptorId;
}
/**
@@ -104,8 +110,11 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
- AndroidEditor editor = getAndroidEditor(viewer);
- UiElementNode rootUiNode = editor.getUiRootNode();
+ if (mEditor == null) {
+ mEditor = getAndroidEditor(viewer);
+ }
+
+ UiElementNode rootUiNode = mEditor.getUiRootNode();
Object[] choices = null; /* An array of ElementDescriptor, or AttributeDescriptor
or String or null */
@@ -245,7 +254,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (current_node.getParentNode().getNodeType() == Node.ELEMENT_NODE) {
grandparent = getDescriptor(current_node.getParentNode().getNodeName());
} else if (current_node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
- grandparent = mRootDescriptor;
+ grandparent = getRootDescriptor();
}
if (grandparent != null) {
for (ElementDescriptor e : grandparent.getChildren()) {
@@ -339,8 +348,11 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
greatGrandParentName = greatGrandParent.getLocalName();
}
}
- choices = FrameworkResourceManager.getInstance().getValues(
- parent, attrInfo.name, greatGrandParentName);
+
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ choices = data.getAttributeValues(parent, attrInfo.name, greatGrandParentName);
+ }
}
} else {
// Editing an attribute's name... Get attributes valid for the parent node.
@@ -378,7 +390,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
} else if (parent_node.getNodeType() == Node.DOCUMENT_NODE) {
// We're editing a text node at the first level (i.e. root node).
// Limit content assist to the only valid root elements.
- choices = mRootDescriptor.getChildren();
+ choices = getRootDescriptor().getChildren();
}
return choices;
}
@@ -509,7 +521,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
* is returned.
*/
private ElementDescriptor getDescriptor(String nodeName) {
- return mRootDescriptor.findChildrenDescriptor(nodeName, true /* recursive */);
+ return getRootDescriptor().findChildrenDescriptor(nodeName, true /* recursive */);
}
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
@@ -539,8 +551,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
public String getErrorMessage() {
return null;
- }
-
+ }
+
/**
* Heuristically extracts the prefix used for determining template relevance
* from the viewer's document. The default implementation returns the String from
@@ -710,6 +722,26 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
}
/**
+ * Computes (if needed) and returns the root descriptor.
+ * @return
+ */
+ private ElementDescriptor getRootDescriptor() {
+ if (mRootDescriptor == null) {
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ IDescriptorProvider descriptorProvider = data.getDescriptorProvider(mDescriptorId);
+
+ if (descriptorProvider != null) {
+ mRootDescriptor = new ElementDescriptor("",
+ descriptorProvider.getRootElementDescriptors());
+ }
+ }
+ }
+
+ return mRootDescriptor;
+ }
+
+ /**
* Returns the active {@link AndroidEditor} matching this source viewer.
*/
private AndroidEditor getAndroidEditor(ITextViewer viewer) {
@@ -729,5 +761,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
return null;
}
+
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
index 74eca96..78e0401 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
@@ -16,10 +16,14 @@
package com.android.ide.eclipse.editors;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
@@ -29,15 +33,18 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
@@ -71,7 +78,7 @@ import java.net.URL;
* source editor. This can be a no-op if desired.
*/
public abstract class AndroidEditor extends FormEditor implements IResourceChangeListener {
-
+
/** Preference name for the current page of this file */
private static final String PREF_CURRENT_PAGE = "_current_page";
@@ -87,9 +94,11 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
/** Page index of the text editor (always the last page) */
private int mTextPageIndex;
/** The text editor */
- private StructuredTextEditor mEditor;
+ private StructuredTextEditor mTextEditor;
/** Listener for the XML model from the StructuredEditor */
private XmlModelStateListener mXmlModelStateListener;
+ /** Listener to update the root node if the resource framework changes */
+ private Runnable mResourceRefreshListener;
/**
* Creates a form editor.
@@ -97,6 +106,16 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
public AndroidEditor() {
super();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+
+ mResourceRefreshListener = new Runnable() {
+ public void run() {
+ commitPages(false /* onSave */);
+
+ // recreate the ui root node always
+ initUiRootNode(true /*force*/);
+ }
+ };
+ AdtPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
}
// ---- Abstract Methods ----
@@ -113,6 +132,12 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
* Derived classes must implement this to add their own specific tabs.
*/
abstract protected void createFormPages();
+
+ /**
+ * Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiManifestNode is recreated even if it already exists.
+ */
+ abstract protected void initUiRootNode(boolean force);
/**
* Subclasses should override this method to process the new XML Model, which XML
@@ -143,6 +168,26 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
protected void createAndroidPages() {
createFormPages();
createTextEditor();
+
+ createUndoRedoActions();
+ }
+
+ /**
+ * Creates undo redo actions for the editor site (so that it works for any page of this
+ * multi-page editor) by re-using the actions defined by the {@link StructuredTextEditor}
+ * (aka the XML text editor.)
+ */
+ private void createUndoRedoActions() {
+ IActionBars bars = getEditorSite().getActionBars();
+ if (bars != null) {
+ IAction action = mTextEditor.getAction(ActionFactory.UNDO.getId());
+ bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), action);
+
+ action = mTextEditor.getAction(ActionFactory.REDO.getId());
+ bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
+
+ bars.updateActionBars();
+ }
}
/**
@@ -155,7 +200,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
if (getEditorInput() instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
- QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+ QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
String pageId;
try {
@@ -177,7 +222,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
// AssertionError from setActivePage when the index is out of bounds.
// Generally speaking we just want to ignore any exception and fall back on the
// first page rather than crash the editor load. Logging the error is enough.
- EditorsPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
+ AdtPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
}
}
}
@@ -224,7 +269,7 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
if (getEditorInput() instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
- QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+ QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
getClass().getSimpleName() + PREF_CURRENT_PAGE);
try {
file.setPersistentProperty(qname, Integer.toString(newPageIndex));
@@ -248,10 +293,10 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
.getPages();
for (int i = 0; i < pages.length; i++) {
- if (((FileEditorInput)mEditor.getEditorInput())
+ if (((FileEditorInput)mTextEditor.getEditorInput())
.getFile().getProject().equals(
event.getResource())) {
- IEditorPart editorPart = pages[i].findEditor(mEditor
+ IEditorPart editorPart = pages[i].findEditor(mTextEditor
.getEditorInput());
pages[i].closeEditor(editorPart, true);
}
@@ -294,6 +339,12 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
}
}
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+
+ if (mResourceRefreshListener != null) {
+ AdtPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
+ mResourceRefreshListener = null;
+ }
+
super.dispose();
}
@@ -447,13 +498,13 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
*/
private void createTextEditor() {
try {
- mEditor = new StructuredTextEditor();
- int index = addPage(mEditor, getEditorInput());
+ mTextEditor = new StructuredTextEditor();
+ int index = addPage(mTextEditor, getEditorInput());
mTextPageIndex = index;
- setPageText(index, mEditor.getTitle());
+ setPageText(index, mTextEditor.getTitle());
- if (!(mEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
- Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ if (!(mTextEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
+ Status status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
"Error opening the Android XML editor. Is the document an XML file?");
throw new RuntimeException("Android XML Editor Error", new CoreException(status));
}
@@ -464,6 +515,8 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
mXmlModelStateListener = new XmlModelStateListener();
xml_model.addModelStateListener(mXmlModelStateListener);
mXmlModelStateListener.modelChanged(xml_model);
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Error while loading editor"); //$NON-NLS-1$
} finally {
xml_model.releaseFromRead();
}
@@ -478,11 +531,11 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
* Returns the ISourceViewer associated with the Structured Text editor.
*/
public final ISourceViewer getStructuredSourceViewer() {
- if (mEditor != null) {
+ if (mTextEditor != null) {
// We can't access mEditor.getSourceViewer() because it is protected,
// however getTextViewer simply returns the SourceViewer casted, so we
// can use it instead.
- return mEditor.getTextViewer();
+ return mTextEditor.getTextViewer();
}
return null;
}
@@ -492,8 +545,8 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
* Editor) or null if not available.
*/
public final IStructuredDocument getStructuredDocument() {
- if (mEditor != null && mEditor.getTextViewer() != null) {
- return (IStructuredDocument) mEditor.getTextViewer().getDocument();
+ if (mTextEditor != null && mTextEditor.getTextViewer() != null) {
+ return (IStructuredDocument) mTextEditor.getTextViewer().getDocument();
}
return null;
}
@@ -539,14 +592,17 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
/**
* Helper class to perform edits on the XML model whilst making sure the
* model has been prepared to be changed.
+ * <p/>
+ * It first gets a model for edition using {@link #getModelForEdit()},
+ * then calls {@link IStructuredModel#aboutToChangeModel()},
+ * then performs the requested action
+ * and finally calls {@link IStructuredModel#changedModel()}
+ * and {@link IStructuredModel#releaseFromEdit()}.
+ * <p/>
+ * The method is synchronous. As soon as the {@link IStructuredModel#changedModel()} method
+ * is called, XML model listeners will be triggered.
*
- * It first gets a model for edition, then calls aboutToChangeModel, then performs the
- * requested action and finally calls changedModel and releaseFromEdit.
- *
- * The method is synchronous. As soon as the changedModel method is called, XML model
- * listeners will be triggered.
- *
- * @param edit_action Something that will change
+ * @param edit_action Something that will change the XML.
*/
public final void editXmlModel(Runnable edit_action) {
IStructuredModel model = getModelForEdit();
@@ -561,11 +617,81 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
}
/**
+ * Starts an "undo recording" session. This is managed by the underlying undo manager
+ * associated to the structured XML model.
+ * <p/>
+ * There <em>must</em> be a corresponding call to {@link #endUndoRecording()}.
+ * <p/>
+ * beginUndoRecording/endUndoRecording calls can be nested (inner calls are ignored, only one
+ * undo operation is recorded.)
+ *
+ * @param label The label for the undo operation. Can be null but we should really try to put
+ * something meaningful if possible.
+ * @return True if the undo recording actually started, false if any kind of error occured.
+ * {@link #endUndoRecording()} should only be called if True is returned.
+ */
+ private final boolean beginUndoRecording(String label) {
+ IStructuredDocument document = getStructuredDocument();
+ if (document != null) {
+ IModelManager mm = StructuredModelManager.getModelManager();
+ if (mm != null) {
+ IStructuredModel model = mm.getModelForEdit(document);
+ if (model != null) {
+ model.beginRecording(this, label);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Ends an "undo recording" session.
+ * <p/>
+ * This is the counterpart call to {@link #beginUndoRecording(String)} and should only be
+ * used if the initial call returned true.
+ */
+ private final void endUndoRecording() {
+ IStructuredDocument document = getStructuredDocument();
+ if (document != null) {
+ IModelManager mm = StructuredModelManager.getModelManager();
+ if (mm != null) {
+ IStructuredModel model = mm.getModelForEdit(document);
+ if (model != null) {
+ model.endRecording(this);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates an "undo recording" session by calling the undoableAction runnable
+ * using {@link #beginUndoRecording(String)} and {@link #endUndoRecording()}.
+ * <p>
+ * You can nest several calls to {@link #wrapUndoRecording(String, Runnable)}, only one
+ * recording session will be created.
+ *
+ * @param label The label for the undo operation. Can be null. Ideally we should really try
+ * to put something meaningful if possible.
+ */
+ public void wrapUndoRecording(String label, Runnable undoableAction) {
+ boolean recording = false;
+ try {
+ recording = beginUndoRecording(label);
+ undoableAction.run();
+ } finally {
+ if (recording) {
+ endUndoRecording();
+ }
+ }
+ }
+
+ /**
* Returns the XML {@link Document} or null if we can't get it
*/
protected final Document getXmlDocument(IStructuredModel model) {
if (model == null) {
- EditorsPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
return null;
}
@@ -577,6 +703,45 @@ public abstract class AndroidEditor extends FormEditor implements IResourceChang
}
/**
+ * Returns the {@link IProject} for the edited file.
+ */
+ public IProject getProject() {
+ if (mTextEditor != null) {
+ IEditorInput input = mTextEditor.getEditorInput();
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput)input;
+ IFile inputFile = fileInput.getFile();
+
+ if (inputFile != null) {
+ return inputFile.getProject();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the {@link PlatformData} for the edited file.
+ */
+ public AndroidTargetData getTargetData() {
+ IProject project = getProject();
+ if (project != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(project);
+
+ if (target != null) {
+ return currentSdk.getTargetData(target);
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
* Listen to changes in the underlying XML model in the structured editor.
*/
private class XmlModelStateListener implements IModelStateListener {
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
index ab17bef..ab17bef 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
index bb0996b..bb0996b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
index 9e3b733..e3de3af 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.editors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import org.eclipse.jface.resource.ImageDescriptor;
@@ -100,8 +101,6 @@ public class IconFactory {
* one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
*/
public Image getIcon(String osName, int color, int shape) {
- EditorsPlugin plugin = EditorsPlugin.getDefault();
-
String key = Character.toString((char) shape) + Integer.toString(color) + osName;
Image icon = mIconMap.get(key);
if (icon == null && !mIconMap.containsKey(key)) {
@@ -143,13 +142,11 @@ public class IconFactory {
* one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
*/
public ImageDescriptor getImageDescriptor(String osName, int color, int shape) {
- EditorsPlugin plugin = EditorsPlugin.getDefault();
-
String key = Character.toString((char) shape) + Integer.toString(color) + osName;
ImageDescriptor id = mImageDescMap.get(key);
if (id == null && !mImageDescMap.containsKey(key)) {
- id = plugin.imageDescriptorFromPlugin(
- AndroidConstants.EDITORS_PLUGIN_ID,
+ id = AdtPlugin.imageDescriptorFromPlugin(
+ AdtPlugin.PLUGIN_ID,
String.format("/icons/%1$s.png", osName)); //$NON-NLS-1$
if (id == null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
index 48fa903..2c779b2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -61,30 +61,6 @@ public abstract class AttributeDescriptor {
public final String getNamespaceUri() {
return mNsUri;
}
-
- /**
- * Returns the XML qualified name of the attribute (case sensitive, with namespace prefix
- * if present)
- *
- * @deprecated
- */
- private final String getXmlName() {
- return mXmlLocalName;
- }
-
- /**
- * Returns the namespace of the attribute.
- *
- * @deprecated
- */
- private final String getNamespace() {
- // For now we hard-code the prefix as being "android"
- if (mXmlLocalName.startsWith("android:")) { //$NON-NLs-1$
- return AndroidConstants.NS_RESOURCES;
- }
-
- return ""; //$NON-NLs-1$
- }
final void setParent(ElementDescriptor parent) {
mParent = parent;
@@ -107,7 +83,7 @@ public abstract class AttributeDescriptor {
IconFactory factory = IconFactory.getInstance();
Image icon;
icon = factory.getIcon(getXmlLocalName(), IconFactory.COLOR_RED, IconFactory.SHAPE_CIRCLE);
- return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+ return icon != null ? icon : AdtPlugin.getAndroidLogo();
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
index 05ae922..05ae922 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
index 9ebf5f1..9ebf5f1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
index f848d79..c84bf57 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
@@ -20,6 +20,8 @@ import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.swt.graphics.Image;
@@ -29,6 +31,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -39,6 +42,8 @@ import java.util.regex.Pattern;
*/
public final class DescriptorsUtils {
+ private static final String DEFAULT_WIDGET_PREFIX = "widget";
+
private static final int JAVADOC_BREAK_LENGTH = 60;
/**
@@ -458,7 +463,8 @@ public final class DescriptorsUtils {
Image icon = elementDescriptor.getIcon();
if (icon != null) {
- sb.append("<form><li style=\"image\" value=\"" + IMAGE_KEY + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append("<form><li style=\"image\" value=\"" + //$NON-NLS-1$
+ IMAGE_KEY + "\">"); //$NON-NLS-1$
} else {
sb.append("<form><p>"); //$NON-NLS-1$
}
@@ -573,13 +579,13 @@ public final class DescriptorsUtils {
// Detects {@link <base>#<name> <text>} where all 3 are optional
Pattern p_link = Pattern.compile("\\{@link\\s+([^#\\}\\s]*)(?:#([^\\s\\}]*))?(?:\\s*([^\\}]*))?\\}(.*)"); //$NON-NLS-1$
// Detects <code>blah</code>
- Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
+ Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
// Detects @blah@, used in hard-coded tooltip descriptors
- Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
+ Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
// Detects a buffer that starts by @ < or { (one that was not matched above)
- Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
+ Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
// Detects everything till the next potential separator, i.e. @ < or {
- Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$
+ Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$
int currentLength = 0;
String text = null;
@@ -668,28 +674,55 @@ public final class DescriptorsUtils {
* <p/>
* This does not override attributes which are not empty.
*/
- public static void setDefaultLayoutAttributes(UiElementNode ui_node) {
- ui_node.setAttributeValue("layout_width", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$
- ui_node.setAttributeValue("layout_height", "wrap_content", false /* override */); //$NON-NLS-1$ $NON-NLS-2$
+ public static void setDefaultLayoutAttributes(UiElementNode ui_node, boolean updateLayout) {
+ // if this ui_node is a layout and we're adding it to a document, use fill_parent for
+ // both W/H. Otherwise default to wrap_layout.
+ boolean fill = ui_node.getDescriptor().hasChildren() &&
+ ui_node.getUiParent() instanceof UiDocumentNode;
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_WIDTH,
+ fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+ false /* override */);
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_HEIGHT,
+ fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+ false /* override */);
String widget_id = getFreeWidgetId(ui_node.getUiRoot(),
- new Object[] {ui_node.getDescriptor().getXmlLocalName(), 1, null });
+ new Object[] { ui_node.getDescriptor().getXmlLocalName(), null, null, null });
if (widget_id != null) {
- ui_node.setAttributeValue("id", "@+id/" + widget_id, false /* override */); //$NON-NLS-1$ $NON-NLS-2$
+ ui_node.setAttributeValue(LayoutConstants.ATTR_ID, "@+id/" + widget_id, //$NON-NLS-1$
+ false /* override */);
}
+
+ ui_node.setAttributeValue(LayoutConstants.ATTR_TEXT, widget_id, false /*override*/);
- UiElementNode ui_parent = ui_node.getUiParent();
- if (ui_parent != null && ui_parent.getDescriptor().getXmlLocalName().equals("RelativeLayout")) { //$NON-NLS-1$
- UiElementNode ui_previous = ui_node.getUiPreviousSibling();
- if (ui_previous != null) {
- String id = ui_previous.getAttributeValue("id"); //$NON-NLS-1$
- if (id != null && id.length() > 0) {
- id = id.replace("@+", "@");
- ui_node.setAttributeValue("layout_below", id, false /* override */);
+ if (updateLayout) {
+ UiElementNode ui_parent = ui_node.getUiParent();
+ if (ui_parent != null &&
+ ui_parent.getDescriptor().getXmlLocalName().equals(
+ LayoutConstants.RELATIVE_LAYOUT)) {
+ UiElementNode ui_previous = ui_node.getUiPreviousSibling();
+ if (ui_previous != null) {
+ String id = ui_previous.getAttributeValue(LayoutConstants.ATTR_ID);
+ if (id != null && id.length() > 0) {
+ id = id.replace("@+", "@"); //$NON-NLS-1$ //$NON-NLS-2$
+ ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW, id,
+ false /* override */);
+ }
}
}
}
-
+ }
+
+ /**
+ * Given a UI root node, returns the first available id that matches the
+ * pattern "prefix%02d".
+ *
+ * @param uiNode The UI node that gives the prefix to match.
+ * @return A suitable generated id
+ */
+ public static String getFreeWidgetId(UiElementNode uiNode) {
+ return getFreeWidgetId(uiNode.getUiRoot(),
+ new Object[] { uiNode.getDescriptor().getXmlLocalName(), null, null, null });
}
/**
@@ -698,19 +731,34 @@ public final class DescriptorsUtils {
*
* For recursion purposes, a "context" is given. Since Java doesn't have in-out parameters
* in methods and we're not going to do a dedicated type, we just use an object array which
- * must contain the following items:
- * - prefix(String): The prefix of the generated id, i.e. "widget"
- * - index(Integer): The minimum index of the generated id
- * - generated(String) The generated widget currently being searched. Must start with null.
+ * must contain one initial item and several are built on the fly just for internal storage:
+ * <ul>
+ * <li> prefix(String): The prefix of the generated id, i.e. "widget". Cannot be null.
+ * <li> index(Integer): The minimum index of the generated id. Must start with null.
+ * <li> generated(String): The generated widget currently being searched. Must start with null.
+ * <li> map(Set<String>): A set of the ids collected so far when walking through the widget
+ * hierarchy. Must start with null.
+ * </ul>
*
- * @param uiRoot The Ui root node where to start searching recusrively.
- * @param params An in-out context of parameters used during recursion, as explaine above.
+ * @param uiRoot The Ui root node where to start searching recursively. For the initial call
+ * you want to pass the document root.
+ * @param params An in-out context of parameters used during recursion, as explained above.
* @return A suitable generated id
*/
- private static String getFreeWidgetId(UiElementNode uiRoot, Object[] params) {
+ @SuppressWarnings("unchecked")
+ private static String getFreeWidgetId(UiElementNode uiRoot,
+ Object[] params) {
+
+ Set<String> map = (Set<String>)params[3];
+ if (map == null) {
+ params[3] = map = new HashSet<String>();
+ }
+
+ int num = params[1] == null ? 0 : ((Integer)params[1]).intValue();
+
String generated = (String) params[2];
+ String prefix = (String) params[0];
if (generated == null) {
- String prefix = (String) params[0];
int pos = prefix.indexOf('.');
if (pos >= 0) {
prefix = prefix.substring(pos + 1);
@@ -719,32 +767,42 @@ public final class DescriptorsUtils {
if (pos >= 0) {
prefix = prefix.substring(pos + 1);
}
- prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$
+ prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$
if (prefix.length() == 0) {
- prefix = "widget";
+ prefix = DEFAULT_WIDGET_PREFIX;
}
- generated = String.format("%1$s%2$02d", prefix, ((Integer)params[1]).intValue());
+
+ do {
+ num++;
+ generated = String.format("%1$s%2$02d", prefix, num); //$NON-NLS-1$
+ } while (map.contains(generated));
+
params[0] = prefix;
+ params[1] = num;
params[2] = generated;
}
- String id = uiRoot.getAttributeValue("id"); //$NON-NLS-1$
+ String id = uiRoot.getAttributeValue(LayoutConstants.ATTR_ID);
if (id != null) {
- id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$
- id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$
- if (id.equals(generated)) {
- // switch to next value
- int num = ((Integer)params[1]).intValue() + 1;
- generated = String.format("%1$s%2$02d", params[0], num);
+ id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$
+ id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$
+ if (map.add(id) && map.contains(generated)) {
+
+ do {
+ num++;
+ generated = String.format("%1$s%2$02d", prefix, num); //$NON-NLS-1$
+ } while (map.contains(generated));
+
params[1] = num;
params[2] = generated;
}
}
-
+
for (UiElementNode uiChild : uiRoot.getUiChildren()) {
getFreeWidgetId(uiChild, params);
}
+ // Note: return params[2] (not "generated") since it could have changed during recursion.
return (String) params[2];
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
index 7d296f7..7d296f7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
index 12ebc38..7d7b1c9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -173,7 +173,7 @@ public class ElementDescriptor {
int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
Image icon = factory.getIcon(mXmlName, color, shape);
- return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+ return icon != null ? icon : AdtPlugin.getAndroidLogo();
}
/**
@@ -190,7 +190,7 @@ public class ElementDescriptor {
int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
ImageDescriptor id = factory.getImageDescriptor(mXmlName, color, shape);
- return id != null ? id : EditorsPlugin.getAndroidLogoDesc();
+ return id != null ? id : AdtPlugin.getAndroidLogoDesc();
}
/* Returns the list of allowed attributes. */
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
index cab9883..cab9883 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
index 903417b..903417b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
new file mode 100644
index 0000000..4c115e9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 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.editors.descriptors;
+
+public interface IDescriptorProvider {
+
+ ElementDescriptor[] getRootElementDescriptors();
+
+ ElementDescriptor getDescriptor();
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
index 93969e9..93969e9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
index 3d3ff29..3d3ff29 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
index 8fb1c7c..8fb1c7c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
index 632471d..632471d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
index 2015d71..2015d71 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
index ed9c897..ed9c897 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
new file mode 100644
index 0000000..c512625
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Base implementation of an {@link IXmlPullParser} for cases where the parser is not sitting
+ * on top of an actual XML file.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public abstract class BasePullParser implements IXmlPullParser {
+
+ protected int mParsingState = START_DOCUMENT;
+
+ public BasePullParser() {
+ }
+
+ // --- new methods to override ---
+
+ public abstract void onNextFromStartDocument();
+ public abstract void onNextFromStartTag();
+ public abstract void onNextFromEndTag();
+
+ // --- basic implementation of IXmlPullParser ---
+
+ public void setFeature(String name, boolean state) throws XmlPullParserException {
+ if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
+ return;
+ }
+ if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
+ return;
+ }
+ throw new XmlPullParserException("Unsupported feature: " + name);
+ }
+
+ public boolean getFeature(String name) {
+ if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+ return true;
+ }
+ if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setProperty(String name, Object value) throws XmlPullParserException {
+ throw new XmlPullParserException("setProperty() not supported");
+ }
+
+ public Object getProperty(String name) {
+ return null;
+ }
+
+ public void setInput(Reader in) throws XmlPullParserException {
+ throw new XmlPullParserException("setInput() not supported");
+ }
+
+ public void setInput(InputStream inputStream, String inputEncoding)
+ throws XmlPullParserException {
+ throw new XmlPullParserException("setInput() not supported");
+ }
+
+ public void defineEntityReplacementText(String entityName, String replacementText)
+ throws XmlPullParserException {
+ throw new XmlPullParserException("defineEntityReplacementText() not supported");
+ }
+
+ public String getNamespacePrefix(int pos) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespacePrefix() not supported");
+ }
+
+ public String getInputEncoding() {
+ return null;
+ }
+
+ public String getNamespace(String prefix) {
+ throw new RuntimeException("getNamespace() not supported");
+ }
+
+ public int getNamespaceCount(int depth) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespaceCount() not supported");
+ }
+
+ public String getNamespaceUri(int pos) throws XmlPullParserException {
+ throw new XmlPullParserException("getNamespaceUri() not supported");
+ }
+
+ public int getColumnNumber() {
+ return -1;
+ }
+
+ public int getLineNumber() {
+ return -1;
+ }
+
+ public String getAttributeType(int arg0) {
+ return "CDATA";
+ }
+
+ public int getEventType() {
+ return mParsingState;
+ }
+
+ public String getText() {
+ return null;
+ }
+
+ public char[] getTextCharacters(int[] arg0) {
+ return null;
+ }
+
+ public boolean isAttributeDefault(int arg0) {
+ return false;
+ }
+
+ public boolean isWhitespace() {
+ return false;
+ }
+
+ public int next() throws XmlPullParserException {
+ switch (mParsingState) {
+ case END_DOCUMENT:
+ throw new XmlPullParserException("Nothing after the end");
+ case START_DOCUMENT:
+ onNextFromStartDocument();
+ break;
+ case START_TAG:
+ onNextFromStartTag();
+ break;
+ case END_TAG:
+ onNextFromEndTag();
+ break;
+ case TEXT:
+ // not used
+ break;
+ case CDSECT:
+ // not used
+ break;
+ case ENTITY_REF:
+ // not used
+ break;
+ case IGNORABLE_WHITESPACE:
+ // not used
+ break;
+ case PROCESSING_INSTRUCTION:
+ // not used
+ break;
+ case COMMENT:
+ // not used
+ break;
+ case DOCDECL:
+ // not used
+ break;
+ }
+
+ return mParsingState;
+ }
+
+ public int nextTag() throws XmlPullParserException, IOException {
+ int eventType = next();
+ if (eventType != START_TAG && eventType != END_TAG) {
+ throw new XmlPullParserException("expected start or end tag", this, null);
+ }
+ return eventType;
+ }
+
+ public String nextText() throws XmlPullParserException, IOException {
+ if (getEventType() != START_TAG) {
+ throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
+ null);
+ }
+ int eventType = next();
+ if (eventType == TEXT) {
+ String result = getText();
+ eventType = next();
+ if (eventType != END_TAG) {
+ throw new XmlPullParserException(
+ "event TEXT it must be immediately followed by END_TAG", this, null);
+ }
+ return result;
+ } else if (eventType == END_TAG) {
+ return "";
+ } else {
+ throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
+ this, null);
+ }
+ }
+
+ public int nextToken() throws XmlPullParserException, IOException {
+ return next();
+ }
+
+ public void require(int type, String namespace, String name) throws XmlPullParserException {
+ if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
+ || (name != null && !name.equals(getName())))
+ throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
index 278b921..77467cd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
@@ -16,12 +16,18 @@
package com.android.ide.eclipse.editors.layout;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
import com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.ide.eclipse.editors.layout.parts.ElementCreateCommand;
+import com.android.ide.eclipse.editors.layout.parts.UiElementEditPart;
import com.android.ide.eclipse.editors.layout.parts.UiElementsEditPartFactory;
import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier;
import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
@@ -44,6 +50,8 @@ import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.CopyCutAction;
+import com.android.ide.eclipse.editors.ui.tree.PasteAction;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.DensityVerifier;
@@ -55,6 +63,7 @@ import com.android.layoutlib.api.ILayoutResult;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.api.IStyleResourceValue;
import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -67,14 +76,22 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.SelectionManager;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.ui.parts.GraphicalEditor;
+import org.eclipse.gef.requests.CreationFactory;
+import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.parts.SelectionSynchronizer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
@@ -85,6 +102,8 @@ import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@@ -98,6 +117,9 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -105,6 +127,7 @@ import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -112,20 +135,25 @@ import java.util.Set;
/**
* Graphical layout editor, based on GEF.
+ * <p/>
+ * To understand GEF: http://www.ibm.com/developerworks/opensource/library/os-gef/
+ * <p/>
+ * To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html
*/
-public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
+public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
implements ILayoutReloadListener {
private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$
/** Reference to the layout editor */
private final LayoutEditor mLayoutEditor;
-
+
/** reference to the file being edited. */
private IFile mEditedFile;
private Clipboard mClipboard;
private Composite mParent;
+ private PaletteRoot mPaletteRoot;
private Text mCountry;
private Text mNetwork;
@@ -141,7 +169,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
private Text mSize2;
private Combo mThemeCombo;
private Button mCreateButton;
-
+
private Label mCountryIcon;
private Label mNetworkIcon;
private Label mLanguageIcon;
@@ -153,18 +181,18 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
private Label mTextInputIcon;
private Label mNavigationIcon;
private Label mSizeIcon;
-
+
private Label mCurrentLayoutLabel;
private Image mWarningImage;
private Image mMatchImage;
private Image mErrorImage;
-
+
/** The {@link FolderConfiguration} representing the state of the UI controls */
private FolderConfiguration mCurrentConfig = new FolderConfiguration();
/** The {@link FolderConfiguration} being edited. */
private FolderConfiguration mEditedConfig;
-
+
private Map<String, Map<String, IResourceValue>> mConfiguredFrameworkRes;
private Map<String, Map<String, IResourceValue>> mConfiguredProjectRes;
private ProjectCallback mProjectCallback;
@@ -173,6 +201,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
private boolean mNeedsRecompute = false;
private int mPlatformThemeCount = 0;
private boolean mDisableUpdates = false;
+ private boolean mActive = false;
private Runnable mFrameworkResourceChangeListener = new Runnable() {
public void run() {
@@ -180,6 +209,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mConfiguredFrameworkRes = null;
updateUIFromResources();
+
mThemeCombo.getParent().layout();
// updateUiFromFramework will reset language/region combo, so we must call
@@ -191,21 +221,21 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// make sure we remove the custom view loader, since its parent class loader is the
// bridge class loader.
mProjectCallback = null;
-
+
recomputeLayout();
}
};
-
+
private final Runnable mConditionalRecomputeRunnable = new Runnable() {
public void run() {
- if (mLayoutEditor.isGraphicalEditorActive()) {
+ if (mActive) {
recomputeLayout();
} else {
mNeedsRecompute = true;
}
}
};
-
+
private final Runnable mUiUpdateFromResourcesRunnable = new Runnable() {
public void run() {
updateUIFromResources();
@@ -217,19 +247,19 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mLayoutEditor = layoutEditor;
setEditDomain(new DefaultEditDomain(this));
setPartName("Layout");
-
+
IconFactory factory = IconFactory.getInstance();
mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$
mMatchImage = factory.getIcon("match"); //$NON-NLS-1$
mErrorImage = factory.getIcon("error"); //$NON-NLS-1$
-
- EditorsPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
+
+ AdtPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
}
-
+
// ------------------------------------
// Methods overridden from base classes
//------------------------------------
-
+
@Override
public void createPartControl(Composite parent) {
mParent = parent;
@@ -237,13 +267,13 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
GridData gd;
mClipboard = new Clipboard(parent.getDisplay());
-
+
parent.setLayout(gl = new GridLayout(1, false));
gl.marginHeight = gl.marginWidth = 0;
-
+
// create the top part for the configuration control
int cols = 10;
-
+
Composite topParent = new Composite(parent, SWT.NONE);
topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
topParent.setLayout(gl = new GridLayout(cols, false));
@@ -339,9 +369,9 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
@Override
public void widgetSelected(SelectionEvent e) {
onOrientationChange();
- }
+ }
});
-
+
new Label(topParent, SWT.NONE).setText("Density");
mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */);
mDensity = new Text(mDensityIcon.getParent(), SWT.BORDER);
@@ -437,7 +467,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
gl.marginWidth = gl.marginHeight = 0;
labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = cols;
-
+
new Label(labelParent, SWT.NONE).setText("Editing config:");
mCurrentLayoutLabel = new Label(labelParent, SWT.NONE);
mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
@@ -449,7 +479,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
sizeParent.setLayout(gl = new GridLayout(3, false));
gl.marginWidth = gl.marginHeight = 0;
gl.horizontalSpacing = 0;
-
+
mSize1 = new Text(sizeParent, SWT.BORDER);
mSize1.setLayoutData(gd = new GridData());
gd.widthHint = 30;
@@ -457,11 +487,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mSize2 = new Text(sizeParent, SWT.BORDER);
mSize2.setLayoutData(gd = new GridData());
gd.widthHint = 30;
-
+
DimensionVerifier verifier = new DimensionVerifier();
mSize1.addVerifyListener(verifier);
mSize2.addVerifyListener(verifier);
-
+
SelectionListener sl = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
onSizeChange();
@@ -470,7 +500,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
onSizeChange();
}
};
-
+
mSize1.addSelectionListener(sl);
mSize2.addSelectionListener(sl);
@@ -488,7 +518,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
separator.setLayoutData(gd = new GridData(
GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));
gd.heightHint = 0;
-
+
mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN);
mThemeCombo.setEnabled(false);
updateUIFromResources();
@@ -521,7 +551,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
}
}
});
-
+
// create a new composite that will contain the standard editor controls.
Composite editorParent = new Composite(parent, SWT.NONE);
editorParent.setLayoutData(new GridData(GridData.FILL_BOTH));
@@ -532,28 +562,31 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
@Override
public void dispose() {
if (mFrameworkResourceChangeListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(
+ AdtPlugin.getDefault().removeResourceChangedListener(
mFrameworkResourceChangeListener);
mFrameworkResourceChangeListener = null;
}
-
+
LayoutReloadMonitor.getMonitor().removeListener(mEditedFile.getProject(), this);
if (mClipboard != null) {
mClipboard.dispose();
mClipboard = null;
}
-
+
super.dispose();
}
-
+
/* (non-Javadoc)
* Creates the palette root.
*/
+ @Override
protected PaletteRoot getPaletteRoot() {
- return PaletteFactory.createPaletteRoot();
+ mPaletteRoot = PaletteFactory.createPaletteRoot(mPaletteRoot,
+ mLayoutEditor.getTargetData());
+ return mPaletteRoot;
}
-
+
public Clipboard getClipboard() {
return mClipboard;
}
@@ -577,22 +610,60 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
firePropertyChange(PROP_DIRTY);
}
+ @Override
+ protected void configurePaletteViewer() {
+ super.configurePaletteViewer();
+
+ // Create a drag source listener on an edit part that is a viewer.
+ // What this does is use DND with a TemplateTransfer type which is actually
+ // the PaletteTemplateEntry held in the PaletteRoot.
+ TemplateTransferDragSourceListener dragSource =
+ new TemplateTransferDragSourceListener(getPaletteViewer());
+
+ // Create a drag source on the palette viewer.
+ // See the drag target associated with the GraphicalViewer in configureGraphicalViewer.
+ getPaletteViewer().addDragSourceListener(dragSource);
+ }
+
/* (non-javadoc)
* Configure the graphical viewer before it receives its contents.
*/
@Override
protected void configureGraphicalViewer() {
super.configureGraphicalViewer();
-
+
GraphicalViewer viewer = getGraphicalViewer();
viewer.setEditPartFactory(new UiElementsEditPartFactory(mParent.getDisplay()));
viewer.setRootEditPart(new ScalableFreeformRootEditPart());
- // TODO: viewer.setKeyHandler()
- // TODO: custom ContextMenuProvider => viewer.setContextMenu & registerContextMenu
+ // Disable the following -- we don't drag *from* the GraphicalViewer yet:
+ // viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
+
+ viewer.addDropTargetListener(new DropListener(viewer));
+ }
+
+ class DropListener extends TemplateTransferDropTargetListener {
+ public DropListener(EditPartViewer viewer) {
+ super(viewer);
+ }
+
+ // TODO explain
+ @Override
+ protected CreationFactory getFactory(final Object template) {
+ return new CreationFactory() {
+ public Object getNewObject() {
+ // We don't know the newly created EditPart since "creating" new
+ // elements is done by ElementCreateCommand.execute() directly by
+ // manipulating the XML elements..
+ return null;
+ }
- viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
- viewer.addDropTargetListener(new TemplateTransferDropTargetListener(viewer));
+ public Object getObjectType() {
+ return template;
+ }
+
+ };
+ }
}
/* (non-javadoc)
@@ -602,31 +673,184 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
protected void initializeGraphicalViewer() {
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(getModel());
-
+
IEditorInput input = getEditorInput();
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
-
+
updateUIFromResources();
LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this);
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
- EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+ AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
}
+ /* (non-javadoc)
+ * Sets the graphicalViewer for this EditorPart.
+ * @param viewer the graphical viewer
+ */
+ @Override
+ protected void setGraphicalViewer(GraphicalViewer viewer) {
+ super.setGraphicalViewer(viewer);
+
+ // TODO: viewer.setKeyHandler()
+ viewer.setContextMenu(createContextMenu(viewer));
+ }
+
+ /**
+ * Used by LayoutEditor.UiEditorActions.selectUiNode to select a new UI Node
+ * created by {@link ElementCreateCommand#execute()}.
+ *
+ * @param uiNodeModel The {@link UiElementNode} to select.
+ */
+ public void selectModel(UiElementNode uiNodeModel) {
+ GraphicalViewer viewer = getGraphicalViewer();
+
+ // Give focus to the graphical viewer (in case the outline has it)
+ viewer.getControl().forceFocus();
+
+ Object editPart = viewer.getEditPartRegistry().get(uiNodeModel);
+
+ if (editPart instanceof EditPart) {
+ viewer.select((EditPart)editPart);
+ }
+ }
+
+
//--------------
// Local methods
//--------------
-
+
public LayoutEditor getLayoutEditor() {
return mLayoutEditor;
}
+ private MenuManager createContextMenu(GraphicalViewer viewer) {
+ MenuManager menuManager = new MenuManager();
+ menuManager.setRemoveAllWhenShown(true);
+ menuManager.addMenuListener(new ActionMenuListener(viewer));
+
+ return menuManager;
+ }
+
+ private class ActionMenuListener implements IMenuListener {
+ private final GraphicalViewer mViewer;
+
+ public ActionMenuListener(GraphicalViewer viewer) {
+ mViewer = viewer;
+ }
+
+ /**
+ * The menu is about to be shown. The menu manager has already been
+ * requested to remove any existing menu item. This method gets the
+ * tree selection and if it is of the appropriate type it re-creates
+ * the necessary actions.
+ */
+ public void menuAboutToShow(IMenuManager manager) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ // filter selected items and only keep those we can handle
+ for (Object obj : mViewer.getSelectedEditParts()) {
+ if (obj instanceof UiElementEditPart) {
+ UiElementEditPart part = (UiElementEditPart) obj;
+ UiElementNode uiNode = part.getUiNode();
+ if (uiNode != null) {
+ selected.add(uiNode);
+ }
+ }
+ }
+
+ if (selected.size() > 0) {
+ doCreateMenuAction(manager, mViewer, selected);
+ }
+ }
+ }
+
+ private void doCreateMenuAction(IMenuManager manager,
+ final GraphicalViewer viewer,
+ final ArrayList<UiElementNode> selected) {
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
+ }
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the
+ // parent is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(mLayoutEditor, getClipboard(),
+ selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
+ }
+ }
+
+ // Append "add" and "remove" actions. They do the same thing as the add/remove
+ // buttons on the side.
+ IconFactory factory = IconFactory.getInstance();
+
+ final UiEditorActions uiActions = mLayoutEditor.getUiEditorActions();
+
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ UiElementNode node = selected != null && selected.size() > 0 ? selected.get(0)
+ : null;
+ uiActions.doAdd(node, viewer.getControl().getShell());
+ }
+ });
+ }
+
+ if (selected != null) {
+ manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doRemove(selected, viewer.getControl().getShell());
+ }
+ });
+
+ manager.add(new Separator());
+
+ manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doUp(selected);
+ }
+ });
+ manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-2$
+ @Override
+ public void run() {
+ uiActions.doDown(selected);
+ }
+ });
+ }
+
+ }
+
/**
* Sets the UI for the edition of a new file.
* @param configuration the configuration of the new file.
@@ -669,7 +893,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
s1 = s2;
s2 = tmp;
}
-
+
switch (orientation) {
default:
case PORTRAIT:
@@ -680,6 +904,105 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
return new Rectangle(0, 0, s1, s1);
}
}
+
+ /**
+ * Renders an Android View described by a {@link ViewElementDescriptor}.
+ * <p/>This uses the <code>wrap_content</code> mode for both <code>layout_width</code> and
+ * <code>layout_height</code>, and use the class name for the <code>text</code> attribute.
+ * @param descriptor the descriptor for the class to render.
+ * @return an ImageData containing the rendering or <code>null</code> if rendering failed.
+ */
+ public ImageData renderWidget(ViewElementDescriptor descriptor) {
+ if (mEditedFile == null) {
+ return null;
+ }
+
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+ if (target == null) {
+ return null;
+ }
+
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ if (data == null) {
+ return null;
+ }
+
+ LayoutBridge bridge = data.getLayoutBridge();
+
+ if (bridge.bridge != null) { // bridge can never be null.
+ ResourceManager resManager = ResourceManager.getInstance();
+
+ ProjectCallback projectCallback = null;
+ Map<String, Map<String, IResourceValue>> configuredProjectResources = null;
+ if (mEditedFile != null) {
+ ProjectResources projectRes = resManager.getProjectResources(
+ mEditedFile.getProject());
+ projectCallback = new ProjectCallback(bridge.classLoader,
+ projectRes, mEditedFile.getProject());
+
+ // get the configured resources for the project
+ // get the resources of the file's project.
+ if (mConfiguredProjectRes == null && projectRes != null) {
+ // make sure they are loaded
+ projectRes.loadAll();
+
+ // get the project resource values based on the current config
+ mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+ }
+
+ configuredProjectResources = mConfiguredProjectRes;
+ } else {
+ // we absolutely need a Map of configured project resources.
+ configuredProjectResources = new HashMap<String, Map<String, IResourceValue>>();
+ }
+
+ // get the framework resources
+ Map<String, Map<String, IResourceValue>> frameworkResources =
+ getConfiguredFrameworkResources();
+
+ if (configuredProjectResources != null && frameworkResources != null) {
+ // get the selected theme
+ int themeIndex = mThemeCombo.getSelectionIndex();
+ if (themeIndex != -1) {
+ String theme = mThemeCombo.getItem(themeIndex);
+
+ // change the string if it's a custom theme to make sure we can
+ // differentiate them
+ if (themeIndex >= mPlatformThemeCount) {
+ theme = "*" + theme; //$NON-NLS-1$
+ }
+
+ // Render a single object as described by the ViewElementDescriptor.
+ WidgetPullParser parser = new WidgetPullParser(descriptor);
+ ILayoutResult result = bridge.bridge.computeLayout(parser,
+ null /* projectKey */,
+ 300 /* width */, 300 /* height */, theme,
+ configuredProjectResources, frameworkResources, projectCallback,
+ null /* logger */);
+
+ // update the UiElementNode with the layout info.
+ if (result.getSuccess() == ILayoutResult.SUCCESS) {
+ BufferedImage largeImage = result.getImage();
+
+ // we need to resize it to the actual widget size, and convert it into
+ // an SWT image object.
+ int width = result.getRootView().getRight();
+ int height = result.getRootView().getBottom();
+ Raster raster = largeImage.getData(new java.awt.Rectangle(width, height));
+ int[] imageDataBuffer = ((DataBufferInt)raster.getDataBuffer()).getData();
+
+ ImageData imageData = new ImageData(width, height, 32,
+ new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
+
+ imageData.setPixels(0, 0, imageDataBuffer.length, imageDataBuffer, 0);
+
+ return imageData;
+ }
+ }
+ }
+ }
+ return null;
+ }
/**
* Reloads this editor, by getting the new model from the {@link LayoutEditor}.
@@ -690,41 +1013,41 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
IEditorInput input = mLayoutEditor.getEditorInput();
setInput(input);
-
+
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
- EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+ AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
}
-
+
/**
* Update the layout editor when the Xml model is changed.
*/
void onXmlModelChanged() {
GraphicalViewer viewer = getGraphicalViewer();
-
+
// try to preserve the selection before changing the content
SelectionManager selMan = viewer.getSelectionManager();
ISelection selection = selMan.getSelection();
-
+
try {
viewer.setContents(getModel());
} finally {
selMan.setSelection(selection);
- }
-
+ }
+
if (mLayoutEditor.isGraphicalEditorActive()) {
recomputeLayout();
} else {
mNeedsRecompute = true;
}
}
-
+
/**
* Update the UI controls state with a given {@link FolderConfiguration}.
* <p/>If a qualifier is not present in the {@link FolderConfiguration} object, the UI control
@@ -745,7 +1068,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mCountry.getText().length() > 0) {
mCountryIcon.setImage(mWarningImage);
}
-
+
mNetworkIcon.setImage(mMatchImage);
NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier();
if (networkQualifier != null) {
@@ -754,7 +1077,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mNetwork.getText().length() > 0) {
mNetworkIcon.setImage(mWarningImage);
}
-
+
mLanguageIcon.setImage(mMatchImage);
LanguageQualifier languageQualifier = config.getLanguageQualifier();
if (languageQualifier != null) {
@@ -763,7 +1086,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mLanguage.getText().length() > 0) {
mLanguageIcon.setImage(mWarningImage);
}
-
+
mRegionIcon.setImage(mMatchImage);
RegionQualifier regionQualifier = config.getRegionQualifier();
if (regionQualifier != null) {
@@ -772,7 +1095,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mRegion.getText().length() > 0) {
mRegionIcon.setImage(mWarningImage);
}
-
+
mOrientationIcon.setImage(mMatchImage);
ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier();
if (orientationQualifier != null) {
@@ -782,7 +1105,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mOrientation.getSelectionIndex() != 0) {
mOrientationIcon.setImage(mWarningImage);
}
-
+
mDensityIcon.setImage(mMatchImage);
PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier();
if (densityQualifier != null) {
@@ -791,7 +1114,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mDensity.getText().length() > 0) {
mDensityIcon.setImage(mWarningImage);
}
-
+
mTouchIcon.setImage(mMatchImage);
TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier();
if (touchQualifier != null) {
@@ -800,7 +1123,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mTouch.getSelectionIndex() != 0) {
mTouchIcon.setImage(mWarningImage);
}
-
+
mKeyboardIcon.setImage(mMatchImage);
KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier();
if (keyboardQualifier != null) {
@@ -818,7 +1141,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mTextInput.getSelectionIndex() != 0) {
mTextInputIcon.setImage(mWarningImage);
}
-
+
mNavigationIcon.setImage(mMatchImage);
NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier();
if (navigationQualifiter != null) {
@@ -828,7 +1151,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mNavigation.getSelectionIndex() != 0) {
mNavigationIcon.setImage(mWarningImage);
}
-
+
mSizeIcon.setImage(mMatchImage);
ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier();
if (sizeQualifier != null) {
@@ -838,7 +1161,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) {
mSizeIcon.setImage(mWarningImage);
}
-
+
// update the string showing the folder name
String current = config.toDisplayString();
mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
@@ -927,6 +1250,10 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
return mLayoutEditor.getUiRootNode();
}
+ void reloadPalette() {
+ PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData());
+ }
+
private void onCountryCodeChange() {
// because mCountry triggers onCountryCodeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -936,7 +1263,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String value = mCountry.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setCountryCodeQualifier(null);
@@ -959,7 +1286,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mCountryIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -973,7 +1300,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String value = mNetwork.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setNetworkCodeQualifier(null);
@@ -996,7 +1323,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mNetworkIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -1013,9 +1340,9 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String value = mLanguage.getText();
-
+
updateRegionUi(null /* projectResources */, null /* frameworkResources */);
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setLanguageQualifier(null);
@@ -1034,11 +1361,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mLanguageIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onRegionChange() {
// because mRegion triggers onRegionChange at each modification, the filling
// of the combo with data will trigger notifications, and we don't want that.
@@ -1048,7 +1375,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String value = mRegion.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setRegionQualifier(null);
@@ -1067,11 +1394,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mRegionIcon.setImage(mErrorImage);
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onOrientationChange() {
// update the current config
int index = mOrientation.getSelectionIndex();
@@ -1081,11 +1408,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else {
mCurrentConfig.setScreenOrientationQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onDensityChange() {
// because mDensity triggers onDensityChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -1095,7 +1422,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String value = mDensity.getText();
-
+
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setPixelDensityQualifier(null);
@@ -1122,7 +1449,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onTouchChange() {
// update the current config
int index = mTouch.getSelectionIndex();
@@ -1132,7 +1459,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else {
mCurrentConfig.setTouchTypeQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
@@ -1146,11 +1473,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else {
mCurrentConfig.setKeyboardStateQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onTextInputChange() {
// update the current config
int index = mTextInput.getSelectionIndex();
@@ -1160,11 +1487,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else {
mCurrentConfig.setTextInputMethodQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onNavigationChange() {
// update the current config
int index = mNavigation.getSelectionIndex();
@@ -1174,11 +1501,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
} else {
mCurrentConfig.setNavigationMethodQualifier(null);
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
private void onSizeChange() {
// because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
@@ -1189,7 +1516,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// update the current config
String size1 = mSize1.getText();
String size2 = mSize2.getText();
-
+
// if only one of the strings is empty, do nothing
if ((size1.length() == 0) ^ (size2.length() == 0)) {
mSizeIcon.setImage(mErrorImage);
@@ -1209,12 +1536,12 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
return;
}
}
-
+
// look for a file to open/create
onConfigurationChange();
}
-
+
/**
* Looks for a file matching the new {@link FolderConfiguration} and attempts to open it.
* <p/>If there is no match, notify the user.
@@ -1237,7 +1564,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
ResourceFolderType.LAYOUT,
mCurrentConfig);
}
-
+
if (match != null) {
if (match.getFile().equals(mEditedFile) == false) {
try {
@@ -1279,7 +1606,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
showErrorInEditor(message);
}
}
-
+
private void onThemeChange() {
int themeIndex = mThemeCombo.getSelectionIndex();
if (themeIndex != -1) {
@@ -1314,10 +1641,10 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// create the label
Label icon = new Label(composite, SWT.NONE);
icon.setImage(mMatchImage);
-
+
return icon;
}
-
+
/**
* Recomputes the layout with the help of layoutlib.
*/
@@ -1328,7 +1655,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
// return false;
if (mEditedFile.exists() == false) {
String message = String.format("Resource '%1$s' does not exist.",
- mEditedFile.getFullPath().toString());
+ mEditedFile.getFullPath().toString());
showErrorInEditor(message);
@@ -1339,126 +1666,156 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
if (mEditedFile.isSynchronized(IResource.DEPTH_ZERO) == false) {
String message = String.format("%1$s is out of sync. Please refresh.",
- mEditedFile.getName());
+ mEditedFile.getName());
showErrorInEditor(message);
// also print it in the error console.
- EditorsPlugin.printErrorToConsole(iProject.getName(), message);
- return;
- }
-
- // check there is actually a model (maybe the file is empty).
- UiDocumentNode model = getModel();
-
- if (model.getUiChildren().size() == 0) {
- showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
+ AdtPlugin.printErrorToConsole(iProject.getName(), message);
return;
}
- EditorsPlugin plugin = EditorsPlugin.getDefault();
- LayoutBridge bridge = plugin.getLayoutBridge();
-
- if (bridge.bridge != null) { // bridge can never be null.
- ResourceManager resManager = ResourceManager.getInstance();
-
- ProjectResources projectRes = resManager.getProjectResources(iProject);
- if (projectRes == null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+ if (target == null) {
+ showErrorInEditor("The project target is not set.");
+ return;
+ }
+
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ if (data == null) {
+ // It can happen that the workspace refreshes while the SDK is loading its
+ // data, which could trigger a redraw of the opened layout if some resources
+ // changed while Eclipse is closed.
+ // In this case data could be null, but this is not an error.
+ // We can just silently return, as all the opened editors are automatically
+ // refreshed once the SDK finishes loading.
+ if (AdtPlugin.getDefault().getSdkLoadStatus(null) != LoadStatus.LOADING) {
+ showErrorInEditor(String.format(
+ "The project target (%s) was not properly loaded.",
+ target.getName()));
+ }
return;
}
- // get the resources of the file's project.
- if (mConfiguredProjectRes == null) {
- // make sure they are loaded
- projectRes.loadAll();
+ // check there is actually a model (maybe the file is empty).
+ UiDocumentNode model = getModel();
- // get the project resource values based on the current config
- mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+ if (model.getUiChildren().size() == 0) {
+ showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
+ return;
}
- // get the framework resources
- Map<String, Map<String, IResourceValue>> frameworkResources =
- getConfiguredFrameworkResources();
+ LayoutBridge bridge = data.getLayoutBridge();
- if (mConfiguredProjectRes != null && frameworkResources != null) {
- if (mProjectCallback == null) {
- mProjectCallback = new ProjectCallback(
- plugin.getLayoutlibBridgeClassLoader(), projectRes, iProject);
+ if (bridge.bridge != null) { // bridge can never be null.
+ ResourceManager resManager = ResourceManager.getInstance();
+
+ ProjectResources projectRes = resManager.getProjectResources(iProject);
+ if (projectRes == null) {
+ return;
}
-
- if (mLogger == null) {
- mLogger = new ILayoutLog() {
- public void error(String message) {
- EditorsPlugin.printErrorToConsole(mEditedFile.getName(), message);
- }
-
- public void error(Throwable error) {
- String message = error.getMessage();
- if (message == null) {
- message = error.getClass().getName();
- }
-
- PrintStream ps = new PrintStream(EditorsPlugin.getErrorStream());
- error.printStackTrace(ps);
- }
-
- public void warning(String message) {
- EditorsPlugin.printToConsole(mEditedFile.getName(), message);
- }
- };
+
+ // get the resources of the file's project.
+ if (mConfiguredProjectRes == null) {
+ // make sure they are loaded
+ projectRes.loadAll();
+
+ // get the project resource values based on the current config
+ mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
}
-
- // get the selected theme
- int themeIndex = mThemeCombo.getSelectionIndex();
- if (themeIndex != -1) {
- String theme = mThemeCombo.getItem(themeIndex);
-
- // change the string if it's a custom theme to make sure we can
- // differentiate them
- if (themeIndex >= mPlatformThemeCount) {
- theme = "*" + theme; //$NON-NLS-1$
+
+ // get the framework resources
+ Map<String, Map<String, IResourceValue>> frameworkResources =
+ getConfiguredFrameworkResources();
+
+ if (mConfiguredProjectRes != null && frameworkResources != null) {
+ if (mProjectCallback == null) {
+ mProjectCallback = new ProjectCallback(
+ bridge.classLoader, projectRes, iProject);
}
-
- // Compute the layout
- UiElementPullParser parser = new UiElementPullParser(getModel());
- Rectangle rect = getBounds();
- ILayoutResult result = bridge.bridge.computeLayout(parser, iProject,
- rect.width, rect.height, theme,
- mConfiguredProjectRes, frameworkResources, mProjectCallback,
- mLogger);
-
- // update the UiElementNode with the layout info.
- if (result.getSuccess() == ILayoutResult.SUCCESS) {
- model.setEditData(result.getImage());
-
- updateNodeWithBounds(result.getRootView());
- } else {
- String message = result.getErrorMessage();
-
- // Reset the edit data for all the nodes.
- resetNodeBounds(model);
-
- if (message != null) {
- // set the error in the top element.
- model.setEditData(message);
+
+ if (mLogger == null) {
+ mLogger = new ILayoutLog() {
+ public void error(String message) {
+ AdtPlugin.printErrorToConsole(mEditedFile.getName(), message);
+ }
+
+ public void error(Throwable error) {
+ String message = error.getMessage();
+ if (message == null) {
+ message = error.getClass().getName();
+ }
+
+ PrintStream ps = new PrintStream(AdtPlugin.getErrorStream());
+ error.printStackTrace(ps);
+ }
+
+ public void warning(String message) {
+ AdtPlugin.printToConsole(mEditedFile.getName(), message);
+ }
+ };
+ }
+
+ // get the selected theme
+ int themeIndex = mThemeCombo.getSelectionIndex();
+ if (themeIndex != -1) {
+ String theme = mThemeCombo.getItem(themeIndex);
+
+ // change the string if it's a custom theme to make sure we can
+ // differentiate them
+ if (themeIndex >= mPlatformThemeCount) {
+ theme = "*" + theme; //$NON-NLS-1$
}
+
+ // Compute the layout
+ UiElementPullParser parser = new UiElementPullParser(getModel());
+ Rectangle rect = getBounds();
+ ILayoutResult result = bridge.bridge.computeLayout(parser,
+ iProject /* projectKey */,
+ rect.width, rect.height, theme,
+ mConfiguredProjectRes, frameworkResources, mProjectCallback,
+ mLogger);
+
+ // update the UiElementNode with the layout info.
+ if (result.getSuccess() == ILayoutResult.SUCCESS) {
+ model.setEditData(result.getImage());
+
+ updateNodeWithBounds(result.getRootView());
+ } else {
+ String message = result.getErrorMessage();
+
+ // Reset the edit data for all the nodes.
+ resetNodeBounds(model);
+
+ if (message != null) {
+ // set the error in the top element.
+ model.setEditData(message);
+ }
+ }
+
+ model.refreshUi();
}
-
- model.refreshUi();
}
+ } else {
+ // SDK is loaded but not the layout library!
+ String message = null;
+ // check whether the bridge managed to load, or not
+ if (bridge.status == LoadStatus.LOADING) {
+ message = String.format(
+ "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
+ mEditedFile.getName());
+ } else {
+ message = String.format("Eclipse failed to load the framework information and the Layout library!");
+ }
+ showErrorInEditor(message);
}
} else {
- String message = null;
+ String message = String.format(
+ "Eclipse is loading the SDK.\n%1$s will refresh automatically once the process is finished.",
+ mEditedFile.getName());
- // check whether the bridge managed to load, or not
- if (bridge.status == LayoutBridge.LoadStatus.LOADING) {
- message = String.format(
- "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
- mEditedFile.getName());
- } else {
- message = String.format("Eclipse failed to load the framework information and the Layout library!");
- }
-
showErrorInEditor(message);
}
} finally {
@@ -1482,10 +1839,10 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
model.refreshUi();
}
-
+
private void resetNodeBounds(UiElementNode node) {
node.setEditData(null);
-
+
List<UiElementNode> children = node.getUiChildren();
for (UiElementNode child : children) {
resetNodeBounds(child);
@@ -1499,10 +1856,10 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
if (viewKey instanceof UiElementNode) {
Rectangle bounds = new Rectangle(r.getLeft(), r.getTop(),
r.getRight()-r.getLeft(), r.getBottom() - r.getTop());
-
+
((UiElementNode)viewKey).setEditData(bounds);
}
-
+
// and then its children.
ILayoutViewInfo[] children = r.getChildren();
if (children != null) {
@@ -1512,11 +1869,11 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
}
}
}
-
+
/*
* (non-Javadoc)
* @see com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener#reloadLayout(boolean, boolean, boolean)
- *
+ *
* Called when the file changes triggered a redraw of the layout
*/
public void reloadLayout(boolean codeChange, boolean rChange, boolean resChange) {
@@ -1525,19 +1882,25 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
if (resChange) {
recompute = true;
- // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
+ // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
// force a reparse in case a value XML file changed.
mConfiguredProjectRes = null;
-
- // clear the cache in the bridge in case a bitmap/9-patch changed.
- EditorsPlugin plugin = EditorsPlugin.getDefault();
- LayoutBridge bridge = plugin.getLayoutBridge();
- if (bridge.bridge != null) {
- bridge.bridge.clearCaches(mEditedFile.getProject());
+ // clear the cache in the bridge in case a bitmap/9-patch changed.
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+ if (target != null) {
+
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ if (data != null) {
+ LayoutBridge bridge = data.getLayoutBridge();
+
+ if (bridge.bridge != null) {
+ bridge.bridge.clearCaches(mEditedFile.getProject());
+ }
+ }
}
-
+
mParent.getDisplay().asyncExec(mUiUpdateFromResourcesRunnable);
}
@@ -1548,7 +1911,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
recompute = true;
}
}
-
+
if (recompute) {
mParent.getDisplay().asyncExec(mConditionalRecomputeRunnable);
}
@@ -1558,11 +1921,19 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
* Responds to a page change that made the Graphical editor page the activated page.
*/
void activated() {
+ mActive = true;
if (mNeedsRecompute) {
recomputeLayout();
}
}
-
+
+ /**
+ * Responds to a page change that made the Graphical editor page the deactivated page
+ */
+ void deactivated() {
+ mActive = false;
+ }
+
/**
* Updates the UI from values in the resources, such as languages, regions, themes, etc...
* This must be called from the UI thread.
@@ -1570,8 +1941,8 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
private void updateUIFromResources() {
ResourceManager manager = ResourceManager.getInstance();
-
- ProjectResources frameworkProject = manager.getFrameworkResources();
+
+ ProjectResources frameworkProject = getFrameworkResources();
mDisableUpdates = true;
@@ -1615,7 +1986,6 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mPlatformThemeCount = themes.size();
themes.clear();
}
-
// now get the languages from the framework.
Set<String> frameworkLanguages = frameworkProject.getLanguages();
if (frameworkLanguages != null) {
@@ -1627,7 +1997,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
ProjectResources project = null;
if (mEditedFile != null) {
project = manager.getProjectResources(mEditedFile.getProject());
-
+
// in cases where the opened file is not linked to a project, this could be null.
if (project != null) {
// get the configured resources for the project
@@ -1706,7 +2076,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
* This is done by making sure the parent is a theme.
* @param value the style to check
* @param styleMap the map of styles for the current project. Key is the style name.
- * @return
+ * @return True if the given <var>style</var> is a theme.
*/
private boolean isTheme(IResourceValue value, Map<String, IResourceValue> styleMap) {
if (value instanceof IStyleResourceValue) {
@@ -1767,15 +2137,15 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
projectResources = ResourceManager.getInstance().getProjectResources(
mEditedFile.getProject());
}
-
+
if (frameworkResources == null) {
- frameworkResources = ResourceManager.getInstance().getFrameworkResources();
+ frameworkResources = getFrameworkResources();
}
-
+
String currentLanguage = mLanguage.getText();
-
+
Set<String> set = null;
-
+
if (projectResources != null) {
set = projectResources.getRegions(currentLanguage);
}
@@ -1803,10 +2173,10 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
private Map<String, Map<String, IResourceValue>> getConfiguredFrameworkResources() {
if (mConfiguredFrameworkRes == null) {
- ProjectResources frameworkRes = ResourceManager.getInstance().getFrameworkResources();
+ ProjectResources frameworkRes = getFrameworkResources();
if (frameworkRes == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
+ AdtPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
}
// get the framework resource values based on the current config
@@ -1821,19 +2191,19 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
* The synchronizer can be used to sync the selection of 2 or more EditPartViewers.
* <p/>
* This is changed from protected to public so that the outline can use it.
- *
+ *
* @return the synchronizer
*/
@Override
public SelectionSynchronizer getSelectionSynchronizer() {
return super.getSelectionSynchronizer();
}
-
+
/**
* Returns the edit domain.
* <p/>
* This is changed from protected to public so that the outline can use it.
- *
+ *
* @return the edit domain
*/
@Override
@@ -1865,10 +2235,9 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
String message = String.format("File 'res/%1$s' is in the way!",
folderName);
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
- return new Status(IStatus.ERROR,
- AndroidConstants.EDITORS_PLUGIN_ID, message);
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
} else if (newLayoutFolder.exists() == false) {
// create it.
newLayoutFolder.mkdir();
@@ -1903,7 +2272,7 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
mParent.getDisplay().asyncExec(new Runnable() {
public void run() {
onConfigurationChange();
- };
+ }
});
}
@@ -1941,16 +2310,16 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
- return new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
message, e2);
} catch (CoreException e2) {
String message = String.format(
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
- EditorsPlugin.displayError("Layout Creation", message);
+ AdtPlugin.displayError("Layout Creation", message);
return e2.getStatus();
}
@@ -1960,4 +2329,27 @@ public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
}
}.schedule();
}
+
+ /**
+ * Returns a {@link ProjectResources} for the framework resources.
+ * @return the framework resources or null if not found.
+ */
+ private ProjectResources getFrameworkResources() {
+ if (mEditedFile != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+
+ if (data != null) {
+ return data.getFrameworkResources();
+ }
+ }
+ }
+ }
+
+ return null;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
new file mode 100644
index 0000000..d4ec5e1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+/**
+ * A bunch of constants that map to either:
+ * <ul>
+ * <li>Android Layouts XML element names (Linear, Relative, Absolute, etc.)
+ * <li>Attributes for layout XML elements.
+ * <li>Values for attributes.
+ * </ul>
+ */
+public class LayoutConstants {
+
+ public static final String RELATIVE_LAYOUT = "RelativeLayout"; //$NON-NLS-1$
+ public static final String LINEAR_LAYOUT = "LinearLayout"; //$NON-NLS-1$
+ public static final String ABSOLUTE_LAYOUT = "AbsoluteLayout"; //$NON-NLS-1$
+
+ public static final String ATTR_TEXT = "text"; //$NON-NLS-1$
+ public static final String ATTR_ID = "id"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_HEIGHT = "layout_height"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_WIDTH = "layout_width"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_TOP = "layout_alignParentTop"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_BOTTOM = "layout_alignParentBottom"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_LEFT = "layout_alignParentLeft";//$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ALIGN_PARENT_RIGHT = "layout_alignParentRight"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_ALIGN_BASELINE = "layout_alignBaseline"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_CENTER_VERTICAL = "layout_centerVertical"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_CENTER_HORIZONTAL = "layout_centerHorizontal"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_TO_RIGHT_OF = "layout_toRightOf"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_TO_LEFT_OF = "layout_toLeftOf"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_BELOW = "layout_below"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_ABOVE = "layout_above"; //$NON-NLS-1$
+
+ public static final String ATTR_LAYOUT_Y = "layout_y"; //$NON-NLS-1$
+ public static final String ATTR_LAYOUT_X = "layout_x"; //$NON-NLS-1$
+
+ public static final String VALUE_WRAP_CONTENT = "wrap_content"; //$NON-NLS-1$
+ public static final String VALUE_FILL_PARENT = "fill_parent"; //$NON-NLS-1$
+ public static final String VALUE_TRUE = "true"; //$NON-NLS-1$
+ public static final String VALUE_N_DIP = "%ddip"; //$NON-NLS-1$
+
+ private LayoutConstants() {
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
index dfec17a..9f39495 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
/**
* Content Assist Processor for /res/layout XML files
@@ -28,6 +28,6 @@ class LayoutContentAssist extends AndroidContentAssist {
* Constructor for LayoutContentAssist
*/
public LayoutContentAssist() {
- super(LayoutDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_LAYOUT);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
index c4a8f5c..c4a8f5c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
index f1bedcb..880ee2b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
@@ -16,14 +16,17 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.EclipseUiHelper;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.UiActions;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -47,12 +50,10 @@ import org.w3c.dom.Document;
*/
public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPartListener {
- public static final String ID = "com.android.ide.eclipse.editors.layout.LayoutEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".layout.LayoutEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiDocumentNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
private GraphicalLayoutEditor mGraphicalEditor;
private int mGraphicalEditorIndex;
@@ -61,13 +62,13 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
/** Custom implementation of {@link IPropertySheetPage} for this editor */
private UiPropertySheetPage mPropertyPage;
+ private UiEditorActions mUiEditorActions;
/**
* Creates the form editor for resources XML files.
*/
public LayoutEditor() {
super();
- initUiRootNode();
}
/**
@@ -82,10 +83,6 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
@Override
public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
getSite().getPage().removePartListener(this);
super.dispose();
@@ -155,7 +152,7 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
getSite().getPage().addPartListener(this);
}
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -222,6 +219,9 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.loadFromXmlNode(xml_doc);
// update the model first, since it is used by the viewers.
@@ -293,7 +293,11 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
}
public void partDeactivated(IWorkbenchPart part) {
- // pass
+ if (part == this) {
+ if (mGraphicalEditor != null && getActivePage() == mGraphicalEditorIndex) {
+ mGraphicalEditor.deactivated();
+ }
+ }
}
public void partOpened(IWorkbenchPart part) {
@@ -301,6 +305,32 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, false /* activate */);
}
+ public class UiEditorActions extends UiActions {
+
+ @Override
+ protected UiDocumentNode getRootNode() {
+ return mUiRootNode;
+ }
+
+ // Select the new item
+ @Override
+ protected void selectUiNode(UiElementNode uiNodeToSelect) {
+ mGraphicalEditor.selectModel(uiNodeToSelect);
+ }
+
+ @Override
+ public void commitPendingXmlChanges() {
+ // Pass. There is nothing to commit before the XML is changed here.
+ }
+ }
+
+ public UiEditorActions getUiEditorActions() {
+ if (mUiEditorActions == null) {
+ mUiEditorActions = new UiEditorActions();
+ }
+ return mUiEditorActions;
+ }
+
// ---- Local Methods ----
/**
@@ -321,38 +351,50 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
return false;
}
- /**
- * Creates the initial UI Root Node, including the known mandatory elements.
- */
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- DocumentDescriptor desc = LayoutDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ DocumentDescriptor desc;
+ if (data == null) {
+ desc = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getLayoutDescriptors().getDescriptor();
+ }
+
+ // get the descriptors from the data.
mUiRootNode = (UiDocumentNode) desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
-
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
-
- if (mOutline != null) {
- mOutline.reloadModel();
- }
-
- if (mGraphicalEditor != null) {
- mGraphicalEditor.recomputeLayout();
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ onDescriptorsChanged(doc);
}
}
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
+ }
+
+ if (mOutline != null) {
+ mOutline.reloadModel();
+ }
+
+ if (mGraphicalEditor != null) {
+ mGraphicalEditor.reloadEditor();
+ mGraphicalEditor.reloadPalette();
+ mGraphicalEditor.recomputeLayout();
+ }
+ }
/**
* Handles a new input, and update the part name.
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
index cf20288..cf20288 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
index 1aa1f4c..1aa1f4c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
index bb075c2..bb075c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
new file mode 100644
index 0000000..94df28f
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.palette.PaletteGroup;
+import org.eclipse.gef.palette.PaletteRoot;
+import org.eclipse.gef.palette.PaletteTemplateEntry;
+
+import java.util.List;
+
+/**
+ * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
+ */
+public class PaletteFactory {
+
+ /** Static factory, nothing to instantiate here. */
+ private PaletteFactory() {
+ }
+
+ public static PaletteRoot createPaletteRoot(PaletteRoot currentPalette,
+ AndroidTargetData targetData) {
+
+ if (currentPalette == null) {
+ currentPalette = new PaletteRoot();
+ }
+
+ for (int n = currentPalette.getChildren().size() - 1; n >= 0; n--) {
+ currentPalette.getChildren().remove(n);
+ }
+
+ if (targetData != null) {
+ addTools(currentPalette);
+ addViews(currentPalette, "Layouts",
+ targetData.getLayoutDescriptors().getLayoutDescriptors());
+ addViews(currentPalette, "Views",
+ targetData.getLayoutDescriptors().getViewDescriptors());
+ }
+
+ return currentPalette;
+ }
+
+ private static void addTools(PaletteRoot paletteRoot) {
+ PaletteGroup group = new PaletteGroup("Tools");
+
+ // Default tools: selection.
+ // Do not use the MarqueeToolEntry since we don't support multiple selection.
+ /* -- Do not put the selection tool. It's the unique tool so it looks useless.
+ Leave this piece of code here in case we want it back later.
+ PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
+ group.add(entry);
+ paletteRoot.setDefaultEntry(entry);
+ */
+
+ paletteRoot.add(group);
+ }
+
+ private static void addViews(PaletteRoot paletteRoot, String groupName,
+ List<ElementDescriptor> descriptors) {
+ PaletteDrawer group = new PaletteDrawer(groupName);
+
+ for (ElementDescriptor desc : descriptors) {
+ PaletteTemplateEntry entry = new PaletteTemplateEntry(
+ desc.getUiName(), // label
+ desc.getTooltip(), // short description
+ desc, // template
+ desc.getImageDescriptor(), // small icon
+ desc.getImageDescriptor() // large icon
+ );
+
+ group.add(entry);
+ }
+
+ paletteRoot.add(group);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
index d91ecbc..81fd2ed 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.layout;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.editors.resources.manager.ProjectClassLoader;
@@ -65,12 +66,17 @@ public final class ProjectCallback implements IProjectCallback {
// load the class.
ProjectClassLoader loader = new ProjectClassLoader(mParentClassLoader, mProject);
- clazz = loader.loadClass(className);
-
- if (clazz != null) {
- mUsed = true;
- mLoadedClasses.put(className, clazz);
- return instantiateClass(clazz, constructorSignature, constructorParameters);
+ try {
+ clazz = loader.loadClass(className);
+
+ if (clazz != null) {
+ mUsed = true;
+ mLoadedClasses.put(className, clazz);
+ return instantiateClass(clazz, constructorSignature, constructorParameters);
+ }
+ } catch (Error e) {
+ // Log this error with the class name we're trying to load and abort.
+ AdtPlugin.log(e, "ProjectCallback.loadView failed to find class %1$s", className); //$NON-NLS-1$
}
return null;
@@ -142,7 +148,7 @@ public final class ProjectCallback implements IProjectCallback {
* @param clazz the class to instantiate
* @param constructorSignature the signature of the constructor to use
* @param constructorParameters the parameters to use in the constructor.
- * @return
+ * @return A new class object, created using a specific constructor and parameters.
* @throws Exception
*/
@SuppressWarnings("unchecked")
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
index 05f8370..3e0f5d8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
@@ -60,7 +60,10 @@ import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
/**
* Implementation of the {@link ContentOutlinePage} to display {@link UiElementNode}.
@@ -84,7 +87,8 @@ class UiContentOutlinePage extends ContentOutlinePage {
mAddAction = new Action("Add...") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
+ UiElementNode node = nodes != null && nodes.size() > 0 ? nodes.get(0) : null;
mUiActions.doAdd(node, viewer.getControl().getShell());
}
@@ -95,9 +99,9 @@ class UiContentOutlinePage extends ContentOutlinePage {
mDeleteAction = new Action("Remove...") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doRemove(node, viewer.getControl().getShell());
+ mUiActions.doRemove(nodes, viewer.getControl().getShell());
}
};
mDeleteAction.setToolTipText("Removes an existing selected element.");
@@ -106,9 +110,9 @@ class UiContentOutlinePage extends ContentOutlinePage {
mUpAction = new Action("Up") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doUp(node);
+ mUiActions.doUp(nodes);
}
};
mUpAction.setToolTipText("Moves the selected element up");
@@ -117,9 +121,9 @@ class UiContentOutlinePage extends ContentOutlinePage {
mDownAction = new Action("Down") {
@Override
public void run() {
- UiElementNode node = getModelSelection();
+ List<UiElementNode> nodes = getModelSelections();
- mUiActions.doDown(node);
+ mUiActions.doDown(nodes);
}
};
mDownAction.setToolTipText("Moves the selected element down");
@@ -250,7 +254,7 @@ class UiContentOutlinePage extends ContentOutlinePage {
* the necessary actions.
*/
public void menuAboutToShow(IMenuManager manager) {
- UiElementNode selected = getModelSelection();
+ List<UiElementNode> selected = getModelSelections();
if (selected != null) {
doCreateMenuAction(manager, selected);
@@ -269,49 +273,74 @@ class UiContentOutlinePage extends ContentOutlinePage {
* the tree view.
*
* @param manager The context menu manager
- * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+ * @param selected The UI node selected in the tree. Can be null, in which case the root
* is to be modified.
*/
- private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
- if (ui_node != null && ui_node.getXmlNode() != null) {
- manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- null, ui_node, true /* cut */));
- manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- null, ui_node, false /* cut */));
- // Paste is not valid if it would add a second element on a terminal element
- // which parent is a document -- an XML document can only have one child. This
- // means paste is valid if the current UI node can have children or if the parent
- // is not a document.
- UiElementNode ui_root = ui_node.getUiRoot();
- if (ui_root.getDescriptor().hasChildren() ||
- !(ui_root.getUiParent() instanceof UiDocumentNode)) {
- manager.add(new PasteAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
- ui_node));
+ private void doCreateMenuAction(IMenuManager manager, List<UiElementNode> selected) {
+
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
+ }
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the parent
+ // is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(mEditor.getLayoutEditor(),
+ mEditor.getClipboard(),
+ selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
}
- manager.add(new Separator());
}
// Append "add" and "remove" actions. They do the same thing as the add/remove
// buttons on the side.
- manager.add(mAddAction);
- manager.add(mDeleteAction);
+ //
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(mAddAction);
+ }
- manager.add(new Separator());
-
- manager.add(mUpAction);
- manager.add(mDownAction);
-
- manager.add(new Separator());
-
- Action propertiesAction = new Action("Properties") {
- @Override
- public void run() {
- EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
- true /* activate */);
- }
- };
- propertiesAction.setToolTipText("Displays properties of the selected element.");
- manager.add(propertiesAction);
+ if (selected != null) {
+ manager.add(mDeleteAction);
+ manager.add(new Separator());
+
+ manager.add(mUpAction);
+ manager.add(mDownAction);
+ }
+
+ if (selected != null && selected.size() == 1) {
+ manager.add(new Separator());
+
+ Action propertiesAction = new Action("Properties") {
+ @Override
+ public void run() {
+ EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
+ true /* activate */);
+ }
+ };
+ propertiesAction.setToolTipText("Displays properties of the selected element.");
+ manager.add(propertiesAction);
+ }
}
/**
@@ -321,18 +350,20 @@ class UiContentOutlinePage extends ContentOutlinePage {
*/
public void reloadModel() {
// Attemps to preserve the UiNode selection, if any
- UiElementNode uiNode = null;
+ List<UiElementNode> uiNodes = null;
try {
// get current selection using the model rather than the edit part as
// reloading the content may change the actual edit part.
- uiNode = getModelSelection();
+ uiNodes = getModelSelections();
// perform the update
getViewer().setContents(mEditor.getModel());
} finally {
// restore selection
- setModelSelection(uiNode);
+ if (uiNodes != null) {
+ setModelSelection(uiNodes.get(0));
+ }
}
}
@@ -344,17 +375,24 @@ class UiContentOutlinePage extends ContentOutlinePage {
* When there is no actual selection, this might still return the root node,
* which is of type {@link UiDocumentTreeEditPart}.
*/
- private UiElementTreeEditPart getViewerSelection() {
+ @SuppressWarnings("unchecked")
+ private List<UiElementTreeEditPart> getViewerSelections() {
ISelection selection = getSelection();
if (selection instanceof StructuredSelection) {
StructuredSelection structuredSelection = (StructuredSelection)selection;
- if (structuredSelection.size() == 1) {
- Object selectedObj = structuredSelection.getFirstElement();
+ if (structuredSelection.size() > 0) {
+ ArrayList<UiElementTreeEditPart> selected = new ArrayList<UiElementTreeEditPart>();
- if (selectedObj instanceof UiElementTreeEditPart) {
- return (UiElementTreeEditPart) selectedObj;
+ for (Iterator it = structuredSelection.iterator(); it.hasNext(); ) {
+ Object selectedObj = it.next();
+
+ if (selectedObj instanceof UiElementTreeEditPart) {
+ selected.add((UiElementTreeEditPart) selectedObj);
+ }
}
+
+ return selected.size() > 0 ? selected : null;
}
}
@@ -368,13 +406,22 @@ class UiContentOutlinePage extends ContentOutlinePage {
* Returns null if there is no selection or if the implicit root is "selected"
* (which actually represents the lack of a real element selection.)
*/
- private UiElementNode getModelSelection() {
+ private List<UiElementNode> getModelSelections() {
- UiElementTreeEditPart part = getViewerSelection();
+ List<UiElementTreeEditPart> parts = getViewerSelections();
- if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
- return (UiElementNode) part.getModel();
+ if (parts != null) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ for (UiElementTreeEditPart part : parts) {
+ if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
+ selected.add((UiElementNode) part.getModel());
+ }
+ }
+
+ return selected.size() > 0 ? selected : null;
}
+
return null;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
new file mode 100644
index 0000000..b0e6fdb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.w3c.dom.Node;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link IXmlPullParser} implementation on top of {@link UiElementNode}.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public final class UiElementPullParser extends BasePullParser {
+
+ private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
+ private UiElementNode mRoot;
+
+ public UiElementPullParser(UiElementNode top) {
+ super();
+ mRoot = top;
+ push(mRoot);
+ }
+
+ private UiElementNode getCurrentNode() {
+ if (mNodeStack.size() > 0) {
+ return mNodeStack.get(mNodeStack.size()-1);
+ }
+
+ return null;
+ }
+
+ private Node getAttribute(int i) {
+ if (mParsingState != START_TAG) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // get the current uiNode
+ UiElementNode uiNode = getCurrentNode();
+
+ // get its xml node
+ Node xmlNode = uiNode.getXmlNode();
+
+ if (xmlNode != null) {
+ return xmlNode.getAttributes().item(i);
+ }
+
+ return null;
+ }
+
+ private void push(UiElementNode node) {
+ mNodeStack.add(node);
+ }
+
+ private UiElementNode pop() {
+ return mNodeStack.remove(mNodeStack.size()-1);
+ }
+
+ // ------------- IXmlPullParser --------
+
+ /**
+ * {@inheritDoc}
+ *
+ * This implementation returns the underlying DOM node.
+ */
+ public Object getViewKey() {
+ return getCurrentNode();
+ }
+
+ // ------------- XmlPullParser --------
+
+ public String getPositionDescription() {
+ return "XML DOM element depth:" + mNodeStack.size();
+ }
+
+ public int getAttributeCount() {
+ UiElementNode node = getCurrentNode();
+ if (node != null) {
+ return node.getUiAttributes().size();
+ }
+
+ return 0;
+ }
+
+ public String getAttributeName(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getLocalName();
+ }
+
+ return null;
+ }
+
+ public String getAttributeNamespace(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getNamespaceURI();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ public String getAttributePrefix(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getPrefix();
+ }
+ return null;
+ }
+
+ public String getAttributeValue(int i) {
+ Node attribute = getAttribute(i);
+ if (attribute != null) {
+ return attribute.getNodeValue();
+ }
+
+ return null;
+ }
+
+ public String getAttributeValue(String namespace, String localName) {
+ // get the current uiNode
+ UiElementNode uiNode = getCurrentNode();
+
+ // get its xml node
+ Node xmlNode = uiNode.getXmlNode();
+
+ if (xmlNode != null) {
+ Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
+ if (attribute != null) {
+ return attribute.getNodeValue();
+ }
+ }
+
+ return null;
+ }
+
+ public int getDepth() {
+ return mNodeStack.size();
+ }
+
+ public String getName() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ return getCurrentNode().getDescriptor().getXmlLocalName();
+ }
+
+ return null;
+ }
+
+ public String getNamespace() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ return getCurrentNode().getDescriptor().getNamespace();
+ }
+
+ return null;
+ }
+
+ public String getPrefix() {
+ if (mParsingState == START_TAG || mParsingState == END_TAG) {
+ // FIXME will NEVER work
+ if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
+ return "android"; //$NON-NLS-1$
+ }
+ }
+
+ return null;
+ }
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (mParsingState == START_TAG) {
+ return getCurrentNode().getUiChildren().size() == 0;
+ }
+
+ throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+ this, null);
+ }
+
+ @Override
+ public void onNextFromStartDocument() {
+ onNextFromStartTag();
+ }
+
+ @Override
+ public void onNextFromStartTag() {
+ // get the current node, and look for text or children (children first)
+ UiElementNode node = getCurrentNode();
+ List<UiElementNode> children = node.getUiChildren();
+ if (children.size() > 0) {
+ // move to the new child, and don't change the state.
+ push(children.get(0));
+
+ // in case the current state is CURRENT_DOC, we set the proper state.
+ mParsingState = START_TAG;
+ } else {
+ if (mParsingState == START_DOCUMENT) {
+ // this handles the case where there's no node.
+ mParsingState = END_DOCUMENT;
+ } else {
+ mParsingState = END_TAG;
+ }
+ }
+ }
+
+ @Override
+ public void onNextFromEndTag() {
+ // look for a sibling. if no sibling, go back to the parent
+ UiElementNode node = getCurrentNode();
+ node = node.getUiNextSibling();
+ if (node != null) {
+ // to go to the sibling, we need to remove the current node,
+ pop();
+ // and add its sibling.
+ push(node);
+ mParsingState = START_TAG;
+ } else {
+ // move back to the parent
+ pop();
+
+ // we have only one element left (mRoot), then we're done with the document.
+ if (mNodeStack.size() == 1) {
+ mParsingState = END_DOCUMENT;
+ } else {
+ mParsingState = END_TAG;
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
index 8093c90..8093c90 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
new file mode 100644
index 0000000..75d10ed
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * {@link IXmlPullParser} implementation to render android widget bitmap.
+ * <p/>The parser emulates a layout that contains just one widget, described by the
+ * {@link ViewElementDescriptor} passed in the constructor.
+ */
+public class WidgetPullParser extends BasePullParser {
+
+ private final ViewElementDescriptor mDescriptor;
+ private String[][] mAttributes = new String[][] {
+ { "text", null },
+ { "layout_width", "wrap_content" },
+ { "layout_height", "wrap_content" },
+ };
+
+ public WidgetPullParser(ViewElementDescriptor descriptor) {
+ mDescriptor = descriptor;
+
+ String[] segments = mDescriptor.getCanonicalClassName().split(AndroidConstants.RE_DOT);
+ mAttributes[0][1] = segments[segments.length-1];
+ }
+
+ public Object getViewKey() {
+ // we need a viewKey or the ILayoutResult will not contain any ILayoutViewInfo
+ return mDescriptor;
+ }
+
+ public int getAttributeCount() {
+ return mAttributes.length; // text attribute
+ }
+
+ public String getAttributeName(int index) {
+ if (index < mAttributes.length) {
+ return mAttributes[index][0];
+ }
+
+ return null;
+ }
+
+ public String getAttributeNamespace(int index) {
+ return AndroidConstants.NS_RESOURCES;
+ }
+
+ public String getAttributePrefix(int index) {
+ // pass
+ return null;
+ }
+
+ public String getAttributeValue(int index) {
+ if (index < mAttributes.length) {
+ return mAttributes[index][1];
+ }
+
+ return null;
+ }
+
+ public String getAttributeValue(String ns, String name) {
+ if (AndroidConstants.NS_RESOURCES.equals(ns)) {
+ for (String[] attribute : mAttributes) {
+ if (name.equals(attribute[0])) {
+ return attribute[1];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public int getDepth() {
+ // pass
+ return 0;
+ }
+
+ public String getName() {
+ return mDescriptor.getXmlLocalName();
+ }
+
+ public String getNamespace() {
+ // pass
+ return null;
+ }
+
+ public String getPositionDescription() {
+ // pass
+ return null;
+ }
+
+ public String getPrefix() {
+ // pass
+ return null;
+ }
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (mParsingState == START_TAG) {
+ return true;
+ }
+
+ throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+ this, null);
+ }
+
+ @Override
+ public void onNextFromStartDocument() {
+ // just go to start_tag
+ mParsingState = START_TAG;
+ }
+
+ @Override
+ public void onNextFromStartTag() {
+ // since we have no children, just go to end_tag
+ mParsingState = END_TAG;
+ }
+
+ @Override
+ public void onNextFromEndTag() {
+ // just one tag. we are done.
+ mParsingState = END_DOCUMENT;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
index c3e9b70..0f388f4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
@@ -16,9 +16,12 @@
package com.android.ide.eclipse.editors.layout.descriptors;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -192,15 +195,24 @@ public final class CustomViewDescriptorService {
private ViewElementDescriptor getDescriptor(IType type, IProject project,
ITypeHierarchy typeHierarchy) {
// check if the type is a built-in View class.
- List<ElementDescriptor> builtInList = LayoutDescriptors.getInstance().getViewDescriptors();
-
+ List<ElementDescriptor> builtInList = null;
+
+ Sdk currentSdk = Sdk.getCurrent();
+ IAndroidTarget target = currentSdk.getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ builtInList = data.getLayoutDescriptors().getViewDescriptors();
+ }
+
String canonicalName = type.getFullyQualifiedName();
- for (ElementDescriptor desc : builtInList) {
- if (desc instanceof ViewElementDescriptor) {
- ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
- if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
- return viewDescriptor;
+ if (builtInList != null) {
+ for (ElementDescriptor desc : builtInList) {
+ if (desc instanceof ViewElementDescriptor) {
+ ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
+ if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
+ return viewDescriptor;
+ }
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
index 8ad2382..cad9ccf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
@@ -24,6 +24,7 @@ import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import java.util.ArrayList;
@@ -34,31 +35,26 @@ import java.util.List;
/**
* Complete description of the layout structure.
*/
-public class LayoutDescriptors {
+public final class LayoutDescriptors implements IDescriptorProvider {
// Public attributes names, attributes descriptors and elements descriptors
public static final String ID_ATTR = "id"; //$NON-NLS-1$
- /** Singleton instance */
- private static LayoutDescriptors sThis;
-
/** The document descriptor. Contains all layouts and views linked together. */
private DocumentDescriptor mDescriptor =
new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$
/** The list of all known ViewLayout descriptors. */
private ArrayList<ElementDescriptor> mLayoutDescriptors = new ArrayList<ElementDescriptor>();
-
+
+ /** Read-Only list of View Descriptors. */
+ private List<ElementDescriptor> mROLayoutDescriptors;
+
/** The list of all known View (not ViewLayout) descriptors. */
private ArrayList<ElementDescriptor> mViewDescriptors = new ArrayList<ElementDescriptor>();
- /** Returns a singleton instance of the {@link LayoutDescriptors}. */
- public static synchronized LayoutDescriptors getInstance() {
- if (sThis == null) {
- sThis = new LayoutDescriptors();
- }
- return sThis;
- }
+ /** Read-Only list of View Descriptors. */
+ private List<ElementDescriptor> mROViewDescriptors;
/** @return the document descriptor. Contains all layouts and views linked together. */
public DocumentDescriptor getDescriptor() {
@@ -67,12 +63,16 @@ public class LayoutDescriptors {
/** @return The read-only list of all known ViewLayout descriptors. */
public List<ElementDescriptor> getLayoutDescriptors() {
- return Collections.unmodifiableList(mLayoutDescriptors);
+ return mROLayoutDescriptors;
}
/** @return The read-only list of all known View (not ViewLayout) descriptors. */
public List<ElementDescriptor> getViewDescriptors() {
- return Collections.unmodifiableList(mViewDescriptors);
+ return mROViewDescriptors;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
}
/**
@@ -118,6 +118,9 @@ public class LayoutDescriptors {
mViewDescriptors = newViews;
mLayoutDescriptors = newLayouts;
mDescriptor.setChildren(newArray);
+
+ mROLayoutDescriptors = Collections.unmodifiableList(mLayoutDescriptors);
+ mROViewDescriptors = Collections.unmodifiableList(mViewDescriptors);
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
index d718ebd..d718ebd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
new file mode 100644
index 0000000..6e79d64
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+/**
+ * Utility methods used when dealing with dropping EditPart on the GLE.
+ * <p/>
+ * This class uses some temporary static storage to avoid excessive allocations during
+ * drop operations. It is expected to only be invoked from the main UI thread with no
+ * concurrent access.
+ */
+class DropFeedback {
+
+ private static final int TOP = 0;
+ private static final int LEFT = 1;
+ private static final int BOTTOM = 2;
+ private static final int RIGHT = 3;
+ private static final int MAX_DIR = RIGHT;
+
+ private static final int sOppositeDirection[] = { BOTTOM, RIGHT, TOP, LEFT };
+
+ private static final UiElementEditPart sTempClosests[] = new UiElementEditPart[4];
+ private static final int sTempMinDists[] = new int[4];
+
+
+ /**
+ * Target information computed from a drop on a RelativeLayout.
+ * We need only one instance of this and it is sRelativeInfo.
+ */
+ private static class RelativeInfo {
+ /** The two target parts 0 and 1. They can be null, meaning a border is used.
+ * The direction from part 0 to 1 is always to-the-right or to-the-bottom. */
+ final UiElementEditPart targetParts[] = new UiElementEditPart[2];
+ /** Direction from the anchor part to the drop point. */
+ int direction;
+ /** The index of the "anchor" part, i.e. the closest one selected by the drop.
+ * This can be either 0 or 1. The corresponding part can be null. */
+ int anchorIndex;
+ }
+
+ /** The single RelativeInfo used to compute results from a drop on a RelativeLayout */
+ private static final RelativeInfo sRelativeInfo = new RelativeInfo();
+ /** A temporary array of 2 {@link UiElementEditPart} to avoid allocations. */
+ private static final UiElementEditPart sTempTwoParts[] = new UiElementEditPart[2];
+
+
+ private DropFeedback() {
+ }
+
+
+ //----- Package methods called by users of this helper class -----
+
+
+ /**
+ * This method is used by {@link ElementCreateCommand#execute()} when a new item
+ * needs to be "dropped" in the current XML document. It creates the new item using
+ * the given descriptor as a child of the given parent part.
+ *
+ * @param parentPart The parent part.
+ * @param descriptor The descriptor for the new XML element.
+ * @param where The drop location (in parent coordinates)
+ * @param actions The helper that actually modifies the XML model.
+ */
+ static void addElementToXml(UiElementEditPart parentPart,
+ ElementDescriptor descriptor, Point where,
+ UiEditorActions actions) {
+
+ String layoutXmlName = getXmlLocalName(parentPart);
+ RelativeInfo info = null;
+ UiElementEditPart sibling = null;
+
+ if (LayoutConstants.LINEAR_LAYOUT.equals(layoutXmlName)) {
+ sibling = findLinearTarget(parentPart, where)[1];
+
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+ info = findRelativeTarget(parentPart, where, sRelativeInfo);
+ if (info != null) {
+ sibling = info.targetParts[info.anchorIndex];
+ sibling = getNextUiSibling(sibling);
+ }
+ }
+
+ if (actions != null) {
+ UiElementNode uiSibling = sibling != null ? sibling.getUiNode() : null;
+ UiElementNode uiParent = parentPart.getUiNode();
+ UiElementNode uiNode = actions.addElement(uiParent, uiSibling, descriptor,
+ false /*updateLayout*/);
+
+ if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutXmlName)) {
+ adjustAbsoluteAttributes(uiNode, where);
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+ adustRelativeAttributes(uiNode, info);
+ }
+ }
+ }
+
+ /**
+ * This method is used by {@link UiLayoutEditPart#showDropTarget(Point)} to compute
+ * highlight information when a drop target is moved over a valid drop area.
+ * <p/>
+ * Since there are no "out" parameters in Java, all the information is returned
+ * via the {@link HighlightInfo} structure passed as parameter.
+ *
+ * @param parentPart The parent part, always a layout.
+ * @param highlightInfo A structure where result is stored to perform highlight.
+ * @param where The target drop point, in parent's coordinates
+ * @return The {@link HighlightInfo} structured passed as a parameter, for convenience.
+ */
+ static HighlightInfo computeDropFeedback(UiLayoutEditPart parentPart,
+ HighlightInfo highlightInfo,
+ Point where) {
+ String layoutType = getXmlLocalName(parentPart);
+
+ if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutType)) {
+ highlightInfo.anchorPoint = where;
+
+ } else if (LayoutConstants.LINEAR_LAYOUT.equals(layoutType)) {
+ boolean isVertical = isVertical(parentPart);
+
+ highlightInfo.childParts = findLinearTarget(parentPart, where);
+ computeLinearLine(parentPart, isVertical, highlightInfo);
+
+ } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutType)) {
+
+ RelativeInfo info = findRelativeTarget(parentPart, where, sRelativeInfo);
+ if (info != null) {
+ highlightInfo.childParts = sRelativeInfo.targetParts;
+ computeRelativeLine(parentPart, info, highlightInfo);
+ }
+ }
+
+ return highlightInfo;
+ }
+
+
+ //----- Misc utilities -----
+
+ /**
+ * Returns the next UI sibling of this part, i.e. the element which is just after in
+ * the UI/XML order in the same parent. Returns null if there's no such part.
+ * <p/>
+ * Note: by "UI sibling" here we mean the sibling in the UiNode hierarchy. By design the
+ * UiNode model has the <em>exact</em> same order as the XML model. This has nothing to do
+ * with the "user interface" order that you see on the rendered Android layouts (e.g. for
+ * LinearLayout they are the same but for AbsoluteLayout or RelativeLayout the UI/XML model
+ * order can be vastly different from the user interface order.)
+ */
+ private static UiElementEditPart getNextUiSibling(UiElementEditPart part) {
+ if (part != null) {
+ UiElementNode uiNode = part.getUiNode();
+ if (uiNode != null) {
+ uiNode = uiNode.getUiNextSibling();
+ }
+ if (uiNode != null) {
+ for (Object childPart : part.getParent().getChildren()) {
+ if (childPart instanceof UiElementEditPart &&
+ ((UiElementEditPart) childPart).getUiNode() == uiNode) {
+ return (UiElementEditPart) childPart;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the XML local name of the ui node associated with this edit part or null.
+ */
+ private static String getXmlLocalName(UiElementEditPart editPart) {
+ UiElementNode uiNode = editPart.getUiNode();
+ if (uiNode != null) {
+ ElementDescriptor desc = uiNode.getDescriptor();
+ if (desc != null) {
+ return desc.getXmlLocalName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adjusts the attributes of a new node dropped in an AbsoluteLayout.
+ *
+ * @param uiNode The new node being dropped.
+ * @param where The drop location (in parent coordinates)
+ */
+ private static void adjustAbsoluteAttributes(final UiElementNode uiNode, final Point where) {
+ if (where == null) {
+ return;
+ }
+ uiNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_X,
+ String.format(LayoutConstants.VALUE_N_DIP, where.x),
+ false /* override */);
+ uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_Y,
+ String.format(LayoutConstants.VALUE_N_DIP, where.y),
+ false /* override */);
+
+ uiNode.commitDirtyAttributesToXml();
+ }
+ });
+ }
+
+ /**
+ * Adjusts the attributes of a new node dropped in a RelativeLayout:
+ * <ul>
+ * <li> anchor part: the one the user selected (or the closest) and to which the new one
+ * will "attach". The anchor part can be null, either because the layout is currently
+ * empty or the user is attaching to an existing empty border.
+ * <li> direction: the direction from the anchor part to the drop point. That's also the
+ * direction from the anchor part to the new part.
+ * <li> the new node; it is created either after the anchor for right or top directions
+ * or before the anchor for left or bottom directions. This means the new part can
+ * reference the id of the anchor part.
+ * </ul>
+ *
+ * Several cases:
+ * <ul>
+ * <li> set: layout_above/below/toLeftOf/toRightOf to point to the anchor.
+ * <li> copy: layout_centerHorizontal for top/bottom directions
+ * <li> copy: layout_centerVertical for left/right directions.
+ * <li> copy: layout_above/below/toLeftOf/toRightOf for the orthogonal direction
+ * (i.e. top/bottom or left/right.)
+ * </ul>
+ *
+ * @param uiNode The new node being dropped.
+ * @param info The context computed by {@link #findRelativeTarget(UiElementEditPart, Point, RelativeInfo)}.
+ */
+ private static void adustRelativeAttributes(final UiElementNode uiNode, RelativeInfo info) {
+ if (uiNode == null || info == null) {
+ return;
+ }
+
+ final UiElementEditPart anchorPart = info.targetParts[info.anchorIndex]; // can be null
+ final int direction = info.direction;
+
+ uiNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ HashMap<String, String> map = new HashMap<String, String>();
+
+ UiElementNode anchorUiNode = anchorPart != null ? anchorPart.getUiNode() : null;
+ String anchorId = anchorUiNode != null
+ ? anchorUiNode.getAttributeValue("id") //$NON-NLS-1$
+ : null;
+
+ if (anchorId == null) {
+ anchorId = DescriptorsUtils.getFreeWidgetId(anchorUiNode);
+ anchorUiNode.setAttributeValue("id", anchorId, true /*override*/); //$NON-NLS-1$
+ }
+
+ if (anchorId != null) {
+ switch(direction) {
+ case TOP:
+ map.put(LayoutConstants.ATTR_LAYOUT_ABOVE, anchorId);
+ break;
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_BELOW, anchorId);
+ break;
+ case LEFT:
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF, anchorId);
+ break;
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF, anchorId);
+ break;
+ }
+
+ switch(direction) {
+ case TOP:
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL));
+
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF));
+ map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF));
+ break;
+ case LEFT:
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL));
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE,
+ anchorUiNode.getAttributeValue(
+ LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE));
+
+ map.put(LayoutConstants.ATTR_LAYOUT_ABOVE,
+ anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_ABOVE));
+ map.put(LayoutConstants.ATTR_LAYOUT_BELOW,
+ anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW));
+ break;
+ }
+ } else {
+ // We don't have an anchor node. Assume we're targeting a border and align
+ // to the parent.
+ switch(direction) {
+ case TOP:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_TOP,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case BOTTOM:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_BOTTOM,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case LEFT:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_LEFT,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ case RIGHT:
+ map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_RIGHT,
+ LayoutConstants.VALUE_TRUE);
+ break;
+ }
+ }
+
+ for (Entry<String, String> entry : map.entrySet()) {
+ uiNode.setAttributeValue(entry.getKey(), entry.getValue(), true /* override */);
+ }
+ uiNode.commitDirtyAttributesToXml();
+ }
+ });
+ }
+
+
+ //----- LinearLayout --------
+
+ /**
+ * For a given parent edit part that MUST represent a LinearLayout, finds the
+ * element before which the location points.
+ * <p/>
+ * This computes the edit part that corresponds to what will be the "next sibling" of the new
+ * element.
+ * <p/>
+ * It returns null if it can't be determined, in which case the element will be added at the
+ * end of the parent child list.
+ *
+ * @return The edit parts that correspond to what will be the "prev" and "next sibling" of the
+ * new element. The previous sibling can be null if adding before the first element.
+ * The next sibling can be null if adding after the last element.
+ */
+ private static UiElementEditPart[] findLinearTarget(UiElementEditPart parent, Point point) {
+ // default orientation is horizontal
+ boolean isVertical = isVertical(parent);
+
+ int target = isVertical ? point.y : point.x;
+
+ UiElementEditPart prev = null;
+ UiElementEditPart next = null;
+
+ for (Object child : parent.getChildren()) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart) child;
+ Point p = childPart.getBounds().getCenter();
+ int middle = isVertical ? p.y : p.x;
+ if (target < middle) {
+ next = childPart;
+ break;
+ }
+ prev = childPart;
+ }
+ }
+
+ sTempTwoParts[0] = prev;
+ sTempTwoParts[1] = next;
+ return sTempTwoParts;
+ }
+
+ /**
+ * Computes the highlight line between two parts.
+ * <p/>
+ * The two parts are listed in HighlightInfo.childParts[2]. Any of the parts
+ * can be null.
+ * The result is stored in HighlightInfo.
+ * <p/>
+ * Caller must clear the HighlightInfo as appropriate before this call.
+ *
+ * @param parentPart The parent part, always a layout.
+ * @param isVertical True for vertical parts, thus computing an horizontal line.
+ * @param highlightInfo The in-out highlight info.
+ */
+ private static void computeLinearLine(UiLayoutEditPart parentPart,
+ boolean isVertical, HighlightInfo highlightInfo) {
+ Rectangle r = parentPart.getBounds();
+
+ if (isVertical) {
+ Point p = null;
+ UiElementEditPart part = highlightInfo.childParts[0];
+ if (part != null) {
+ p = part.getBounds().getBottom();
+ } else {
+ part = highlightInfo.childParts[1];
+ if (part != null) {
+ p = part.getBounds().getTop();
+ }
+ }
+ if (p != null) {
+ // horizontal line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(0, p.y);
+ highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p.setLocation(r.width / 2, p.y);
+ }
+ } else {
+ Point p = null;
+ UiElementEditPart part = highlightInfo.childParts[0];
+ if (part != null) {
+ p = part.getBounds().getRight();
+ } else {
+ part = highlightInfo.childParts[1];
+ if (part != null) {
+ p = part.getBounds().getLeft();
+ }
+ }
+ if (p != null) {
+ // vertical line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(p.x, 0);
+ highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p.setLocation(p.x, r.height / 2);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the linear layout is marked as vertical.
+ *
+ * @param parent The a layout part that must be a LinearLayout
+ * @return True if the linear layout has a vertical orientation attribute.
+ */
+ private static boolean isVertical(UiElementEditPart parent) {
+ String orientation = parent.getStringAttr("orientation"); //$NON-NLS-1$
+ boolean isVertical = "vertical".equals(orientation) || //$NON-NLS-1$
+ "1".equals(orientation); //$NON-NLS-1$
+ return isVertical;
+ }
+
+
+ //----- RelativeLayout --------
+
+ /**
+ * Finds the "target" relative layout item for the drop operation & feedback.
+ * <p/>
+ * If the drop point is exactly on a current item, simply returns the side the drop will occur
+ * compared to the center of that element. For the actual XML, we'll need to insert *after*
+ * that element to make sure that referenced are defined in the right order.
+ * In that case the result contains two elements, the second one always being on the right or
+ * bottom side of the first one. When insert in XML, we want to insert right before that
+ * second element or at the end of the child list if the second element is null.
+ * <p/>
+ * If the drop point is not exactly on a current element, find the closest in each
+ * direction and align with the two closest of these.
+ *
+ * @return null if we fail to find anything (such as there are currently no items to compare
+ * with); otherwise fills the {@link RelativeInfo} and return it.
+ */
+ private static RelativeInfo findRelativeTarget(UiElementEditPart parent,
+ Point point,
+ RelativeInfo outInfo) {
+
+ for (int i = 0; i < 4; i++) {
+ sTempMinDists[i] = Integer.MAX_VALUE;
+ sTempClosests[i] = null;
+ }
+
+
+ for (Object child : parent.getChildren()) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart) child;
+ Rectangle r = childPart.getBounds();
+ if (r.contains(point)) {
+
+ float rx = ((float)(point.x - r.x) / (float)r.width ) - 0.5f;
+ float ry = ((float)(point.y - r.y) / (float)r.height) - 0.5f;
+
+ /* TOP
+ * \ /
+ * \ /
+ * L X R
+ * / \
+ * / \
+ * BOT
+ */
+
+ int index = 0;
+ if (Math.abs(rx) >= Math.abs(ry)) {
+ if (rx < 0) {
+ outInfo.direction = LEFT;
+ index = 1;
+ } else {
+ outInfo.direction = RIGHT;
+ }
+ } else {
+ if (ry < 0) {
+ outInfo.direction = TOP;
+ index = 1;
+ } else {
+ outInfo.direction = BOTTOM;
+ }
+ }
+
+ outInfo.anchorIndex = index;
+ outInfo.targetParts[index] = childPart;
+ outInfo.targetParts[1 - index] = findClosestPart(childPart,
+ outInfo.direction);
+
+ return outInfo;
+ }
+
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, TOP);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, LEFT);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, BOTTOM);
+ computeClosest(point, childPart, sTempClosests, sTempMinDists, RIGHT);
+ }
+ }
+
+ UiElementEditPart closest = null;
+ int minDist = Integer.MAX_VALUE;
+ int minDir = -1;
+
+ for (int i = 0; i <= MAX_DIR; i++) {
+ if (sTempClosests[i] != null && sTempMinDists[i] < minDist) {
+ closest = sTempClosests[i];
+ minDist = sTempMinDists[i];
+ minDir = i;
+ }
+ }
+
+ if (closest != null) {
+ int index = 0;
+ switch(minDir) {
+ case TOP:
+ case LEFT:
+ index = 0;
+ break;
+ case BOTTOM:
+ case RIGHT:
+ index = 1;
+ break;
+ }
+ outInfo.anchorIndex = index;
+ outInfo.targetParts[index] = closest;
+ outInfo.targetParts[1 - index] = findClosestPart(closest, sOppositeDirection[minDir]);
+ outInfo.direction = sOppositeDirection[minDir];
+ return outInfo;
+ }
+
+ return null;
+ }
+
+ /**
+ * Computes the highlight line for a drop on a RelativeLayout.
+ * <p/>
+ * The line is always placed on the side of the anchor part indicated by the
+ * direction. The direction always point from the anchor part to the drop point.
+ * <p/>
+ * If there's no anchor part, use the other one with a reversed direction.
+ * <p/>
+ * On output, this updates the {@link HighlightInfo}.
+ */
+ private static void computeRelativeLine(UiLayoutEditPart parentPart,
+ RelativeInfo relInfo,
+ HighlightInfo highlightInfo) {
+
+ UiElementEditPart[] parts = relInfo.targetParts;
+ int dir = relInfo.direction;
+ int index = relInfo.anchorIndex;
+ UiElementEditPart part = parts[index];
+
+ if (part == null) {
+ dir = sOppositeDirection[dir];
+ part = parts[1 - index];
+ }
+ if (part == null) {
+ // give up if both parts are null
+ return;
+ }
+
+ Rectangle r = part.getBounds();
+ Point p = null;
+ switch(dir) {
+ case TOP:
+ p = r.getTop();
+ break;
+ case BOTTOM:
+ p = r.getBottom();
+ break;
+ case LEFT:
+ p = r.getLeft();
+ break;
+ case RIGHT:
+ p = r.getRight();
+ break;
+ }
+
+ highlightInfo.anchorPoint = p;
+
+ r = parentPart.getBounds();
+ switch(dir) {
+ case TOP:
+ case BOTTOM:
+ // horizontal line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(0, p.y);
+ highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p;
+ break;
+ case LEFT:
+ case RIGHT:
+ // vertical line with middle anchor point
+ highlightInfo.tempPoints[0].setLocation(p.x, 0);
+ highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+ highlightInfo.linePoints = highlightInfo.tempPoints;
+ highlightInfo.anchorPoint = p;
+ break;
+ }
+ }
+
+ /**
+ * Given a certain reference point (drop point), computes the distance to the given
+ * part in the given direction. For example if direction is top, only accepts parts which
+ * bottom is above the reference point, computes their distance and then updates the
+ * current minimal distances and current closest parts arrays accordingly.
+ */
+ private static void computeClosest(Point refPoint,
+ UiElementEditPart compareToPart,
+ UiElementEditPart[] currClosests,
+ int[] currMinDists,
+ int direction) {
+ Rectangle r = compareToPart.getBounds();
+
+ Point p = null;
+ boolean usable = false;
+
+ switch(direction) {
+ case TOP:
+ p = r.getBottom();
+ usable = p.y <= refPoint.y;
+ break;
+ case BOTTOM:
+ p = r.getTop();
+ usable = p.y >= refPoint.y;
+ break;
+ case LEFT:
+ p = r.getRight();
+ usable = p.x <= refPoint.x;
+ break;
+ case RIGHT:
+ p = r.getLeft();
+ usable = p.x >= refPoint.x;
+ break;
+ }
+
+ if (usable) {
+ int d = p.getDistance2(refPoint);
+ if (d < currMinDists[direction]) {
+ currMinDists[direction] = d;
+ currClosests[direction] = compareToPart;
+ }
+ }
+ }
+
+ /**
+ * Given a reference parts, finds the closest part in the parent in the given direction.
+ * For example if direction is top, finds the closest sibling part which is above the
+ * reference part and non-overlapping (they can touch.)
+ */
+ private static UiElementEditPart findClosestPart(UiElementEditPart referencePart,
+ int direction) {
+ if (referencePart == null || referencePart.getParent() == null) {
+ return null;
+ }
+
+ Rectangle r = referencePart.getBounds();
+ Point ref = null;
+ switch(direction) {
+ case TOP:
+ ref = r.getTop();
+ break;
+ case BOTTOM:
+ ref = r.getBottom();
+ break;
+ case LEFT:
+ ref = r.getLeft();
+ break;
+ case RIGHT:
+ ref = r.getRight();
+ break;
+ }
+
+ int minDist = Integer.MAX_VALUE;
+ UiElementEditPart closestPart = null;
+
+ for (Object childPart : referencePart.getParent().getChildren()) {
+ if (childPart != referencePart && childPart instanceof UiElementEditPart) {
+ r = ((UiElementEditPart) childPart).getBounds();
+ Point p = null;
+ boolean usable = false;
+
+ switch(direction) {
+ case TOP:
+ p = r.getBottom();
+ usable = p.y <= ref.y;
+ break;
+ case BOTTOM:
+ p = r.getTop();
+ usable = p.y >= ref.y;
+ break;
+ case LEFT:
+ p = r.getRight();
+ usable = p.x <= ref.x;
+ break;
+ case RIGHT:
+ p = r.getLeft();
+ usable = p.x >= ref.x;
+ break;
+ }
+
+ if (usable) {
+ int d = p.getDistance2(ref);
+ if (d < minDist) {
+ minDist = d;
+ closestPart = (UiElementEditPart) childPart;
+ }
+ }
+ }
+ }
+
+ return closestPart;
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
new file mode 100644
index 0000000..d36d9f7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.commands.Command;
+
+/**
+ * A command that knows how to instantiate a new element based on a given {@link ElementDescriptor},
+ * the parent {@link UiElementEditPart} and an optional target location.
+ */
+public class ElementCreateCommand extends Command {
+
+ /** Descriptor of the new element to create */
+ private final ElementDescriptor mDescriptor;
+ /** The edit part that hosts the new edit part */
+ private final UiElementEditPart mParentPart;
+ /** The drop location in parent coordinates */
+ private final Point mTargetPoint;
+
+ /**
+ * Creates a new {@link ElementCreateCommand}.
+ *
+ * @param descriptor Descriptor of the new element to create
+ * @param targetPart The edit part that hosts the new edit part
+ * @param targetPoint The drop location in parent coordinates
+ */
+ public ElementCreateCommand(ElementDescriptor descriptor,
+ UiElementEditPart targetPart, Point targetPoint) {
+ mDescriptor = descriptor;
+ mParentPart = targetPart;
+ mTargetPoint = targetPoint;
+ }
+
+ // --- Methods inherited from Command ---
+
+ @Override
+ public boolean canExecute() {
+ return mDescriptor != null &&
+ mParentPart != null &&
+ mParentPart.getUiNode() != null &&
+ mParentPart.getUiNode().getEditor() instanceof LayoutEditor;
+ }
+
+ @Override
+ public void execute() {
+ super.execute();
+ UiElementNode uiParent = mParentPart.getUiNode();
+ if (uiParent != null) {
+ final AndroidEditor editor = uiParent.getEditor();
+ if (editor instanceof LayoutEditor) {
+ ((LayoutEditor) editor).wrapUndoRecording(
+ String.format("Create %1$s", mDescriptor.getXmlLocalName()),
+ new Runnable() {
+ public void run() {
+ UiEditorActions actions = ((LayoutEditor) editor).getUiEditorActions();
+ if (actions != null) {
+ DropFeedback.addElementToXml(mParentPart, mDescriptor, mTargetPoint,
+ actions);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void redo() {
+ throw new UnsupportedOperationException("redo not supported by this command"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void undo() {
+ throw new UnsupportedOperationException("undo not supported by this command"); //$NON-NLS-1$
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
new file mode 100644
index 0000000..f863037
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+
+/**
+ * The figure used to draw basic elements.
+ * <p/>
+ * The figure is totally empty and transparent except for the selection border.
+ */
+class ElementFigure extends Figure {
+
+ private boolean mIsSelected;
+ private Rectangle mInnerBounds;
+
+ public ElementFigure() {
+ setOpaque(false);
+ }
+
+ public void setSelected(boolean isSelected) {
+ if (isSelected != mIsSelected) {
+ mIsSelected = isSelected;
+ repaint();
+ }
+ }
+
+ @Override
+ public void setBounds(Rectangle rect) {
+ super.setBounds(rect);
+
+ mInnerBounds = getBounds().getCopy();
+ if (mInnerBounds.width > 0) {
+ mInnerBounds.width--;
+ }
+ if (mInnerBounds.height > 0) {
+ mInnerBounds.height--;
+ }
+ }
+
+ public Rectangle getInnerBounds() {
+ return mInnerBounds;
+ }
+
+ @Override
+ protected void paintBorder(Graphics graphics) {
+ super.paintBorder(graphics);
+
+ if (mIsSelected) {
+ graphics.setLineWidth(1);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setForegroundColor(ColorConstants.red);
+ graphics.drawRectangle(getInnerBounds());
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
new file mode 100644
index 0000000..55ed39b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+/**
+ * The figure used to draw the feedback on a layout.
+ * <p/>
+ * By default the figure is transparent and empty.
+ * The base {@link ElementFigure} knows how to draw the selection border.
+ * This figure knows how to draw the drop feedback.
+ */
+class LayoutFigure extends ElementFigure {
+
+ private HighlightInfo mHighlightInfo;
+
+ public LayoutFigure() {
+ super();
+ }
+
+ public void setHighlighInfo(HighlightInfo highlightInfo) {
+ mHighlightInfo = highlightInfo;
+ repaint();
+ }
+
+ /**
+ * Paints the "border" for this figure.
+ * <p/>
+ * The parent {@link Figure#paint(Graphics)} calls {@link #paintFigure(Graphics)} then
+ * {@link #paintClientArea(Graphics)} then {@link #paintBorder(Graphics)}. Here we thus
+ * draw the actual highlight border but also the highlight anchor lines and points so that
+ * we can make sure they are all drawn on top of the border.
+ * <p/>
+ * Note: This method doesn't really need to restore its graphic state. The parent
+ * Figure will do it for us.
+ * <p/>
+ *
+ * @param graphics The Graphics object used for painting
+ */
+ @Override
+ protected void paintBorder(Graphics graphics) {
+ super.paintBorder(graphics);
+
+ if (mHighlightInfo == null) {
+ return;
+ }
+
+ // Draw the border. We want other highlighting to be drawn on top of the border.
+ if (mHighlightInfo.drawDropBorder) {
+ graphics.setLineWidth(3);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setForegroundColor(ColorConstants.green);
+ graphics.drawRectangle(getInnerBounds().getCopy().shrink(1, 1));
+ }
+
+ Rectangle bounds = getBounds();
+ int bx = bounds.x;
+ int by = bounds.y;
+ int w = bounds.width;
+ int h = bounds.height;
+
+ // Draw frames of target child parts, if any
+ if (mHighlightInfo.childParts != null) {
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_DOT);
+ graphics.setForegroundColor(ColorConstants.lightBlue);
+ for (UiElementEditPart part : mHighlightInfo.childParts) {
+ if (part != null) {
+ graphics.drawRectangle(part.getBounds().getCopy().translate(bx, by));
+ }
+ }
+ }
+
+ // Draw the target line, if any
+ if (mHighlightInfo.linePoints != null) {
+ int x1 = mHighlightInfo.linePoints[0].x;
+ int y1 = mHighlightInfo.linePoints[0].y;
+ int x2 = mHighlightInfo.linePoints[1].x;
+ int y2 = mHighlightInfo.linePoints[1].y;
+
+ // if the line is right to the edge, draw it one pixel more inside so that the
+ // full 2-pixel width be visible.
+ if (x1 <= 0) x1++;
+ if (x2 <= 0) x2++;
+ if (y1 <= 0) y1++;
+ if (y2 <= 0) y2++;
+
+ if (x1 >= w - 1) x1--;
+ if (x2 >= w - 1) x2--;
+ if (y1 >= h - 1) y1--;
+ if (y2 >= h - 1) y2--;
+
+ x1 += bx;
+ x2 += bx;
+ y1 += by;
+ y2 += by;
+
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_DASH);
+ graphics.setLineCap(SWT.CAP_ROUND);
+ graphics.setForegroundColor(ColorConstants.orange);
+ graphics.drawLine(x1, y1, x2, y2);
+ }
+
+ // Draw the anchor point, if any
+ if (mHighlightInfo.anchorPoint != null) {
+ int x = mHighlightInfo.anchorPoint.x;
+ int y = mHighlightInfo.anchorPoint.y;
+
+ // If the point is right on the edge, draw it one pixel inside so that it
+ // matches the highlight line. It makes it slightly more visible that way.
+ if (x <= 0) x++;
+ if (y <= 0) y++;
+ if (x >= w - 1) x--;
+ if (y >= h - 1) y--;
+ x += bx;
+ y += by;
+
+ graphics.setLineWidth(2);
+ graphics.setLineStyle(SWT.LINE_SOLID);
+ graphics.setLineCap(SWT.CAP_ROUND);
+ graphics.setForegroundColor(ColorConstants.orange);
+ graphics.drawLine(x-5, y-5, x+5, y+5);
+ graphics.drawLine(x-5, y+5, x+5, y-5);
+ // 7 * cos(45) == 5 so we use 8 for the circle radius (it looks slightly better than 7)
+ graphics.setLineWidth(1);
+ graphics.drawOval(x-8, y-8, 16, 16);
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
index 53a87f5..2f7636d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
@@ -27,7 +27,14 @@ import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
+import org.eclipse.gef.requests.DropRequest;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
@@ -149,4 +156,57 @@ public class UiDocumentEditPart extends UiElementEditPart {
protected void showSelection() {
// no selection at this level.
}
+
+ @Override
+ protected void createEditPolicies() {
+ super.createEditPolicies();
+
+ // This policy indicates this a root component that cannot be removed
+ installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
+
+ installLayoutEditPolicy(this);
+ }
+
+ /**
+ * Returns the EditPart that should be used as the target for the specified Request.
+ * For instance this is called during drag'n'drop with a CreateRequest.
+ * <p/>
+ * For the root document, we want the first child edit part to the be the target
+ * since an XML document can have only one root element.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public EditPart getTargetEditPart(Request request) {
+ if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+ // We refuse the drop if it's not in the bounds of the document.
+ if (request instanceof DropRequest) {
+ Point where = ((DropRequest) request).getLocation().getCopy();
+ UiElementNode uiNode = getUiNode();
+ if (uiNode instanceof UiDocumentNode) {
+ // Take the bounds of the background image as the valid drop zone
+ Object editData = uiNode.getEditData();
+ if (editData instanceof BufferedImage) {
+ BufferedImage image = (BufferedImage)editData;
+ int w = image.getWidth();
+ int h = image.getHeight();
+ if (where.x > w || where.y > h) {
+ return null;
+ }
+ }
+
+ }
+ }
+
+ // For the root document, we want the first child edit part to the be the target
+ // since an XML document can have only one root element.
+ if (getChildren().size() > 0) {
+ Object o = getChildren().get(0);
+ if (o instanceof EditPart) {
+ return ((EditPart) o).getTargetEditPart(request);
+ }
+ }
+ }
+ return super.getTargetEditPart(request);
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
index af22afb..af22afb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
new file mode 100644
index 0000000..d873005
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editpolicies.LayoutEditPolicy;
+import org.eclipse.gef.editpolicies.SelectionEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.gef.requests.DropRequest;
+import org.eclipse.gef.tools.SelectEditPartTracker;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * An {@link EditPart} for a {@link UiElementNode}.
+ */
+public abstract class UiElementEditPart extends AbstractGraphicalEditPart
+ implements IUiUpdateListener {
+
+ public UiElementEditPart(UiElementNode uiElementNode) {
+ setModel(uiElementNode);
+ }
+
+ //-------------------------
+ // Derived classes must define these
+
+ abstract protected void hideSelection();
+ abstract protected void showSelection();
+
+ //-------------------------
+ // Base class overrides
+
+ @Override
+ public DragTracker getDragTracker(Request request) {
+ return new SelectEditPartTracker(this);
+ }
+
+ @Override
+ protected void createEditPolicies() {
+ /*
+ * This is no longer needed, as a selection edit policy is set by the parent layout.
+ * Leave this code commented out right now, I'll want to play with this later.
+ *
+ installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE,
+ new NonResizableSelectionEditPolicy(this));
+ */
+ }
+
+ /* (non-javadoc)
+ * Returns a List containing the children model objects.
+ * Must not return null, instead use the super which returns an empty list.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected List getModelChildren() {
+ return getUiNode().getUiChildren();
+ }
+
+ @Override
+ public void activate() {
+ super.activate();
+ getUiNode().addUpdateListener(this);
+ }
+
+ @Override
+ public void deactivate() {
+ super.deactivate();
+ getUiNode().removeUpdateListener(this);
+ }
+
+ @Override
+ protected void refreshVisuals() {
+ if (getFigure().getParent() != null) {
+ ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
+ }
+
+ // update the visuals of the children as well
+ refreshChildrenVisuals();
+ }
+
+ protected void refreshChildrenVisuals() {
+ if (children != null) {
+ for (Object child : children) {
+ if (child instanceof UiElementEditPart) {
+ UiElementEditPart childPart = (UiElementEditPart)child;
+ childPart.refreshVisuals();
+ }
+ }
+ }
+ }
+
+ //-------------------------
+ // IUiUpdateListener implementation
+
+ public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
+ // TODO: optimize by refreshing only when needed
+ switch(state) {
+ case ATTR_UPDATED:
+ refreshVisuals();
+ break;
+ case CHILDREN_CHANGED:
+ refreshChildren();
+
+ // new children list, need to update the layout
+ refreshVisuals();
+ break;
+ case CREATED:
+ refreshVisuals();
+ break;
+ case DELETED:
+ // pass
+ break;
+ }
+ }
+
+ //-------------------------
+ // Local methods
+
+ /** @return The object model casted to an {@link UiElementNode} */
+ public final UiElementNode getUiNode() {
+ return (UiElementNode) getModel();
+ }
+
+ protected final ElementDescriptor getDescriptor() {
+ return getUiNode().getDescriptor();
+ }
+
+ protected final UiElementEditPart getEditPartParent() {
+ EditPart parent = getParent();
+ if (parent instanceof UiElementEditPart) {
+ return (UiElementEditPart)parent;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a given XML attribute.
+ * @param attrName The local name of the attribute.
+ * @return the attribute as a {@link String}, if it exists, or <code>null</code>
+ */
+ protected final String getStringAttr(String attrName) {
+ UiElementNode uiNode = getUiNode();
+ if (uiNode.getXmlNode() != null) {
+ Node xmlNode = uiNode.getXmlNode();
+ if (xmlNode != null) {
+ NamedNodeMap nodeAttributes = xmlNode.getAttributes();
+ if (nodeAttributes != null) {
+ Node attr = nodeAttributes.getNamedItemNS(
+ AndroidConstants.NS_RESOURCES, attrName);
+ if (attr != null) {
+ return attr.getNodeValue();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected final Rectangle getBounds() {
+ UiElementNode model = (UiElementNode)getModel();
+
+ Object editData = model.getEditData();
+
+ if (editData != null) {
+ // assert with fully qualified class name to prevent import changes to another
+ // Rectangle class.
+ assert (editData instanceof org.eclipse.draw2d.geometry.Rectangle);
+
+ return (Rectangle)editData;
+ }
+
+ // return a dummy rect
+ return new Rectangle(0, 0, 0, 0);
+ }
+
+ /**
+ * Returns the EditPart that should be used as the target for the specified Request.
+ * <p/>
+ * For instance this is called during drag'n'drop with a CreateRequest.
+ * <p/>
+ * Reject being a target for elements which descriptor does not allow children.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public EditPart getTargetEditPart(Request request) {
+ if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+ // Reject being a target for elements which descriptor does not allow children.
+ if (!getUiNode().getDescriptor().hasChildren()) {
+ return null;
+ }
+ }
+ return super.getTargetEditPart(request);
+ }
+
+ /**
+ * Used by derived classes {@link UiDocumentEditPart} and {@link UiLayoutEditPart}
+ * to accept drag'n'drop of new items from the palette.
+ *
+ * @param layoutEditPart The layout edit part where this policy is installed. It can
+ * be either a {@link UiDocumentEditPart} or a {@link UiLayoutEditPart}.
+ */
+ protected void installLayoutEditPolicy(final UiElementEditPart layoutEditPart) {
+ // This policy indicates how elements can be constrained by the layout.
+ // TODO Right now we use the XY layout policy since our constraints are
+ // handled by the android rendering engine rather than GEF. Tweak as
+ // appropriate.
+ installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutEditPolicy() {
+
+ /**
+ * We don't allow layout children to be resized yet.
+ * <p/>
+ * Typical choices would be:
+ * <ul>
+ * <li> ResizableEditPolicy, to allow for selection, move and resize.
+ * <li> NonResizableEditPolicy, to allow for selection, move but not resize.
+ * <li> SelectionEditPolicy to allow for only selection.
+ * </ul>
+ * <p/>
+ * TODO: make this depend on the part layout. For an AbsoluteLayout we should
+ * probably use a NonResizableEditPolicy and SelectionEditPolicy for the rest.
+ * Whether to use ResizableEditPolicy or NonResizableEditPolicy should depend
+ * on the child in an AbsoluteLayout.
+ */
+ @Override
+ protected EditPolicy createChildEditPolicy(EditPart child) {
+ if (child instanceof UiElementEditPart) {
+ return new NonResizableSelectionEditPolicy((UiElementEditPart) child);
+ }
+ return null;
+ }
+
+ @Override
+ protected Command getCreateCommand(CreateRequest request) {
+ // We store the ElementDescriptor in the request.factory.type
+ Object newType = request.getNewObjectType();
+ if (newType instanceof ElementDescriptor) {
+ Point where = request.getLocation().getCopy();
+ Point origin = getLayoutContainer().getClientArea().getLocation();
+ where.translate(origin.getNegated());
+
+ // The host is the EditPart where this policy is installed,
+ // e.g. this UiElementEditPart.
+ EditPart host = getHost();
+ if (host instanceof UiElementEditPart) {
+
+ return new ElementCreateCommand((ElementDescriptor) newType,
+ (UiElementEditPart) host,
+ where);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected Command getMoveChildrenCommand(Request request) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void showLayoutTargetFeedback(Request request) {
+ super.showLayoutTargetFeedback(request);
+
+ // for debugging
+ // System.out.println("target: " + request.toString() + " -- " + layoutEditPart.getUiNode().getBreadcrumbTrailDescription(false));
+
+ if (layoutEditPart instanceof UiLayoutEditPart &&
+ request instanceof DropRequest) {
+ Point where = ((DropRequest) request).getLocation().getCopy();
+ Point origin = getLayoutContainer().getClientArea().getLocation();
+ where.translate(origin.getNegated());
+
+ ((UiLayoutEditPart) layoutEditPart).showDropTarget(where);
+ }
+ }
+
+ @Override
+ protected void eraseLayoutTargetFeedback(Request request) {
+ super.eraseLayoutTargetFeedback(request);
+ if (layoutEditPart instanceof UiLayoutEditPart) {
+ ((UiLayoutEditPart) layoutEditPart).hideDropTarget();
+ }
+ }
+
+ @Override
+ protected IFigure createSizeOnDropFeedback(CreateRequest createRequest) {
+ // TODO understand if this is useful for us or remove
+ return super.createSizeOnDropFeedback(createRequest);
+ }
+
+ });
+ }
+
+ protected static class NonResizableSelectionEditPolicy extends SelectionEditPolicy {
+
+ private final UiElementEditPart mEditPart;
+
+ public NonResizableSelectionEditPolicy(UiElementEditPart editPart) {
+ mEditPart = editPart;
+ }
+
+ @Override
+ protected void hideSelection() {
+ mEditPart.hideSelection();
+ }
+
+ @Override
+ protected void showSelection() {
+ mEditPart.showSelection();
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
index fd788dd..fd788dd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
index de6c404..de6c404 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
index 18dcd9c..18dcd9c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
index d9433ca..43a70a5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
@@ -18,11 +18,9 @@ package com.android.ide.eclipse.editors.layout.parts;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.ContainerEditPolicy;
@@ -35,6 +33,24 @@ import org.eclipse.gef.requests.CreateRequest;
*/
public final class UiLayoutEditPart extends UiElementEditPart {
+ static class HighlightInfo {
+ public boolean drawDropBorder;
+ public UiElementEditPart[] childParts;
+ public Point anchorPoint;
+ public Point linePoints[];
+
+ public final Point tempPoints[] = new Point[] { new Point(), new Point() };
+
+ public void clear() {
+ drawDropBorder = false;
+ childParts = null;
+ anchorPoint = null;
+ linePoints = null;
+ }
+ }
+
+ private final HighlightInfo mHighlightInfo = new HighlightInfo();
+
public UiLayoutEditPart(UiElementNode uiElementNode) {
super(uiElementNode);
}
@@ -49,39 +65,51 @@ public final class UiLayoutEditPart extends UiElementEditPart {
return null;
}
});
+
+ installLayoutEditPolicy(this);
}
@Override
protected IFigure createFigure() {
- Label f = new Label();
+ IFigure f = new LayoutFigure();
f.setLayoutManager(new XYLayout());
return f;
}
@Override
- protected void hideSelection() {
+ protected void showSelection() {
IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(null);
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(true);
}
}
@Override
- protected void showSelection() {
+ protected void hideSelection() {
IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.red, 1));
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(false);
}
}
-
- public void showDropTarget() {
- IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.blue, 1));
+
+ public void showDropTarget(Point where) {
+ if (where != null) {
+ mHighlightInfo.clear();
+ mHighlightInfo.drawDropBorder = true;
+ DropFeedback.computeDropFeedback(this, mHighlightInfo, where);
+
+ IFigure f = getFigure();
+ if (f instanceof LayoutFigure) {
+ ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+ }
}
}
public void hideDropTarget() {
- hideSelection();
+ mHighlightInfo.clear();
+ IFigure f = getFigure();
+ if (f instanceof LayoutFigure) {
+ ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
index 4359e23..4359e23 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
index b427ead..05329f3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
@@ -18,10 +18,8 @@ package com.android.ide.eclipse.editors.layout.parts;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.XYLayout;
/**
* Graphical edit part for an {@link UiElementNode} that represents a View.
@@ -31,26 +29,27 @@ public class UiViewEditPart extends UiElementEditPart {
public UiViewEditPart(UiElementNode uiElementNode) {
super(uiElementNode);
}
-
+
@Override
protected IFigure createFigure() {
- Label f = new Label();
+ IFigure f = new ElementFigure();
+ f.setLayoutManager(new XYLayout());
return f;
}
-
+
@Override
- protected void hideSelection() {
+ protected void showSelection() {
IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(null);
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(true);
}
}
@Override
- protected void showSelection() {
+ protected void hideSelection() {
IFigure f = getFigure();
- if (f instanceof Label) {
- f.setBorder(new LineBorder(ColorConstants.red, 1));
+ if (f instanceof ElementFigure) {
+ ((ElementFigure) f).setSelected(false);
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
index 62b5e8a..62b5e8a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
index 75cf4b6..45cbc77 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
@@ -16,14 +16,20 @@
package com.android.ide.eclipse.editors.layout.uimodel;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IProject;
+
+import java.util.List;
/**
* Specialized version of {@link UiElementNode} for the {@link ViewElementDescriptor}s.
@@ -59,12 +65,26 @@ public class UiViewElementNode extends UiElementNode {
// Limitation: right now the layout behaves as if everything was
// owned by a FrameLayout.
// TODO replace by something user-configurable.
- for (ElementDescriptor desc : LayoutDescriptors.getInstance().getLayoutDescriptors()) {
- if (desc instanceof ViewElementDescriptor &&
- desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
- layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
- need_xmlns = true;
- break;
+
+ List<ElementDescriptor> layoutDescriptors = null;
+ IProject project = getEditor().getProject();
+ if (project != null) {
+ Sdk currentSdk = Sdk.getCurrent();
+ IAndroidTarget target = currentSdk.getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = currentSdk.getTargetData(target);
+ layoutDescriptors = data.getLayoutDescriptors().getLayoutDescriptors();
+ }
+ }
+
+ if (layoutDescriptors != null) {
+ for (ElementDescriptor desc : layoutDescriptors) {
+ if (desc instanceof ViewElementDescriptor &&
+ desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
+ layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
+ need_xmlns = true;
+ break;
+ }
}
}
} else if (ui_parent instanceof UiViewElementNode){
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
index e43c984..b40e458 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.editors.manifest;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
/**
* Content Assist Processor for AndroidManifest.xml
@@ -29,6 +28,6 @@ final class ManifestContentAssist extends AndroidContentAssist {
* Constructor for ManifestContentAssist
*/
public ManifestContentAssist() {
- super(new ElementDescriptor[] { AndroidManifestDescriptors.MANIFEST_ELEMENT });
+ super(AndroidTargetData.DESCRIPTOR_MANIFEST);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
index 666a066..d0f8d7b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
@@ -16,10 +16,11 @@
package com.android.ide.eclipse.editors.manifest;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.editors.manifest.pages.ApplicationPage;
@@ -59,19 +60,30 @@ public final class ManifestEditor extends AndroidEditor {
/** Root node of the UI element hierarchy */
private UiElementNode mUiManifestNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/** The Application Page tab */
private ApplicationPage mAppPage;
/** The Overview Manifest Page tab */
private OverviewPage mOverviewPage;
+ /** The Permission Page tab */
+ private PermissionPage mPermissionPage;
+ /** The Instrumentation Page tab */
+ private InstrumentationPage mInstrumentationPage;
+
+ private IFileListener mMarkerMonitor;
+
/**
* Creates the form editor for AndroidManifest.xml.
*/
public ManifestEditor() {
super();
- initUiManifestNode();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+
+ ResourceMonitor.getMonitor().removeFileListener(mMarkerMonitor);
}
/**
@@ -83,16 +95,19 @@ public final class ManifestEditor extends AndroidEditor {
return mUiManifestNode;
}
- // ---- Base Class Overrides ----
-
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
+ /**
+ * Returns the Manifest descriptors for the file being edited.
+ */
+ public AndroidManifestDescriptors getManifestDescriptors() {
+ AndroidTargetData data = getTargetData();
+ if (data != null) {
+ return data.getManifestDescriptors();
}
- super.dispose();
+
+ return null;
}
+
+ // ---- Base Class Overrides ----
/**
* Returns whether the "save as" operation is supported by this editor.
@@ -115,10 +130,10 @@ public final class ManifestEditor extends AndroidEditor {
try {
addPage(mOverviewPage = new OverviewPage(this));
addPage(mAppPage = new ApplicationPage(this));
- addPage(new PermissionPage(this));
- addPage(new InstrumentationPage(this));
+ addPage(mPermissionPage = new PermissionPage(this));
+ addPage(mInstrumentationPage = new InstrumentationPage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -130,6 +145,7 @@ public final class ManifestEditor extends AndroidEditor {
super.setInput(input);
IFile inputFile = getInputFile();
if (inputFile != null) {
+ startMonitoringMarkers();
setPartName(String.format("%1$s Manifest", inputFile.getProject().getName()));
}
}
@@ -141,29 +157,54 @@ public final class ManifestEditor extends AndroidEditor {
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
- mUiManifestNode.setXmlDocument(xml_doc);
- if (xml_doc != null) {
+ // create the ui root node on demand.
+ initUiRootNode(false /*force*/);
+
+ loadFromXml(xml_doc);
+
+ super.xmlModelChanged(xml_doc);
+ }
+
+ private void loadFromXml(Document xmlDoc) {
+ mUiManifestNode.setXmlDocument(xmlDoc);
+ if (xmlDoc != null) {
ElementDescriptor manifest_desc = mUiManifestNode.getDescriptor();
try {
XPath xpath = AndroidXPathFactory.newXPath();
Node node = (Node) xpath.evaluate("/" + manifest_desc.getXmlName(), //$NON-NLS-1$
- xml_doc,
+ xmlDoc,
XPathConstants.NODE);
assert node != null && node.getNodeName().equals(manifest_desc.getXmlName());
// Refresh the manifest UI node and all its descendants
mUiManifestNode.loadFromXmlNode(node);
-
- startMonitoringMarkers();
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
manifest_desc.getXmlName());
}
}
-
- super.xmlModelChanged(xml_doc);
}
+ private void onDescriptorsChanged(UiElementNode oldManifestNode) {
+ mUiManifestNode.reloadFromXmlNode(oldManifestNode.getXmlNode());
+
+ if (mOverviewPage != null) {
+ mOverviewPage.refreshUiApplicationNode();
+ }
+
+ if (mAppPage != null) {
+ mAppPage.refreshUiApplicationNode();
+ }
+
+ if (mPermissionPage != null) {
+ mPermissionPage.refreshUiNode();
+ }
+
+ if (mInstrumentationPage != null) {
+ mInstrumentationPage.refreshUiNode();
+ }
+ }
+
/**
* Reads and processes the current markers and adds a listener for marker changes.
*/
@@ -172,13 +213,15 @@ public final class ManifestEditor extends AndroidEditor {
if (inputFile != null) {
updateFromExistingMarkers(inputFile);
- ResourceMonitor.getMonitor().addFileListener(new IFileListener() {
+ mMarkerMonitor = new IFileListener() {
public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
if (file.equals(inputFile)) {
processMarkerChanges(markerDeltas);
}
}
- }, IResourceDelta.CHANGED);
+ };
+
+ ResourceMonitor.getMonitor().addFileListener(mMarkerMonitor, IResourceDelta.CHANGED);
}
}
@@ -192,14 +235,22 @@ public final class ManifestEditor extends AndroidEditor {
// get the markers for the file
IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true,
IResource.DEPTH_ZERO);
+
+ AndroidManifestDescriptors desc = getManifestDescriptors();
+ if (desc != null) {
+ ElementDescriptor appElement = desc.getApplicationElement();
+
+ if (appElement != null) {
+ UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+ appElement.getXmlName());
+ List<UiElementNode> children = app_ui_node.getUiChildren();
- UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
- AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
- List<UiElementNode> children = app_ui_node.getUiChildren();
-
- for (IMarker marker : markers) {
- processMarker(marker, children, IResourceDelta.ADDED);
+ for (IMarker marker : markers) {
+ processMarker(marker, children, IResourceDelta.ADDED);
+ }
+ }
}
+
} catch (CoreException e) {
// findMarkers can throw an exception, in which case, we'll do nothing.
}
@@ -210,12 +261,15 @@ public final class ManifestEditor extends AndroidEditor {
* @param markerDeltas the list of {@link IMarkerDelta}
*/
private void processMarkerChanges(IMarkerDelta[] markerDeltas) {
- UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
- AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
- List<UiElementNode> children = app_ui_node.getUiChildren();
-
- for (IMarkerDelta markerDelta : markerDeltas) {
- processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+ AndroidManifestDescriptors descriptors = getManifestDescriptors();
+ if (descriptors != null && descriptors.getApplicationElement() != null) {
+ UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+ descriptors.getApplicationElement().getXmlName());
+ List<UiElementNode> children = app_ui_node.getUiChildren();
+
+ for (IMarkerDelta markerDelta : markerDeltas) {
+ processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+ }
}
}
@@ -259,56 +313,62 @@ public final class ManifestEditor extends AndroidEditor {
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiManifestNode is recreated even if it already exists.
*/
- private void initUiManifestNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The manifest UI node is always created, even if there's no corresponding XML node.
- if (mUiManifestNode == null) {
- ElementDescriptor manifest_desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;
- mUiManifestNode = manifest_desc.createUiNode();
+ if (mUiManifestNode != null && force == false) {
+ return;
+ }
+
+
+ AndroidManifestDescriptors manifestDescriptor = getManifestDescriptors();
+
+ if (manifestDescriptor != null) {
+ // save the old manifest node if it exists
+ UiElementNode oldManifestNode = mUiManifestNode;
+
+ ElementDescriptor manifestElement = manifestDescriptor.getManifestElement();
+ mUiManifestNode = manifestElement.createUiNode();
mUiManifestNode.setEditor(this);
// Similarly, always create the /manifest/application and /manifest/uses-sdk nodes
- ElementDescriptor app_desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
+ ElementDescriptor appElement = manifestDescriptor.getApplicationElement();
boolean present = false;
for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
- if (ui_node.getDescriptor() == app_desc) {
+ if (ui_node.getDescriptor() == appElement) {
present = true;
break;
}
}
if (!present) {
- mUiManifestNode.appendNewUiChild(app_desc);
+ mUiManifestNode.appendNewUiChild(appElement);
}
- app_desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
+ appElement = manifestDescriptor.getUsesSdkElement();
present = false;
for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
- if (ui_node.getDescriptor() == app_desc) {
+ if (ui_node.getDescriptor() == appElement) {
present = true;
break;
}
}
if (!present) {
- mUiManifestNode.appendNewUiChild(app_desc);
+ mUiManifestNode.appendNewUiChild(appElement);
}
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
-
- mUiManifestNode.reloadFromXmlNode(mUiManifestNode.getXmlNode());
- if (mOverviewPage != null) {
- mOverviewPage.refreshUiApplicationNode();
- }
- if (mAppPage != null) {
- mAppPage.refreshUiApplicationNode();
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ if (oldManifestNode != null) {
+ onDescriptorsChanged(oldManifestNode);
+ }
+ } else {
+ // create a dummy descriptor/uinode until we have real descriptors
+ ElementDescriptor desc = new ElementDescriptor("manifest", //$NON-NLS-1$
+ "temporary descriptors due to missing decriptors", //$NON-NLS-1$
+ null /*tooltip*/, null /*sdk_url*/, null /*attributes*/,
+ null /*children*/, false /*mandatory*/);
+ mUiManifestNode = desc.createUiNode();
+ mUiManifestNode.setEditor(this);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
index 911faa1..911faa1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
index e33e1ef..e33e1ef 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
index 171eaee..87a14ad 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
@@ -16,17 +16,18 @@
package com.android.ide.eclipse.editors.manifest.descriptors;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import org.eclipse.core.runtime.IStatus;
@@ -45,7 +46,7 @@ import java.util.Map.Entry;
* However their sub-elements and attributes are created only when the SDK changes or is
* loaded the first time.
*/
-public class AndroidManifestDescriptors {
+public final class AndroidManifestDescriptors implements IDescriptorProvider {
private static final String MANIFEST_NODE_NAME = "manifest"; //$NON-NLS-1$
private static final String ANDROID_MANIFEST_STYLEABLE = "AndroidManifest"; //$NON-NLS-1$
@@ -57,28 +58,28 @@ public class AndroidManifestDescriptors {
public static final String PACKAGE_ATTR = "package"; //$NON-NLS-1$
/** The {@link ElementDescriptor} for the root Manifest element. */
- public static final ElementDescriptor MANIFEST_ELEMENT;
+ private final ElementDescriptor MANIFEST_ELEMENT;
/** The {@link ElementDescriptor} for the root Application element. */
- public static final ElementDescriptor APPLICATION_ELEMENT;
+ private final ElementDescriptor APPLICATION_ELEMENT;
/** The {@link ElementDescriptor} for the root Instrumentation element. */
- public static final ElementDescriptor INTRUMENTATION_ELEMENT;
+ private final ElementDescriptor INTRUMENTATION_ELEMENT;
/** The {@link ElementDescriptor} for the root Permission element. */
- public static final ElementDescriptor PERMISSION_ELEMENT;
+ private final ElementDescriptor PERMISSION_ELEMENT;
/** The {@link ElementDescriptor} for the root UsesPermission element. */
- public static final ElementDescriptor USES_PERMISSION_ELEMENT;
+ private final ElementDescriptor USES_PERMISSION_ELEMENT;
/** The {@link ElementDescriptor} for the root UsesSdk element. */
- public static final ElementDescriptor USES_SDK_ELEMENT;
+ private final ElementDescriptor USES_SDK_ELEMENT;
/** The {@link ElementDescriptor} for the root PermissionGroup element. */
- public static final ElementDescriptor PERMISSION_GROUP_ELEMENT;
+ private final ElementDescriptor PERMISSION_GROUP_ELEMENT;
/** The {@link ElementDescriptor} for the root PermissionTree element. */
- public static final ElementDescriptor PERMISSION_TREE_ELEMENT;
+ private final ElementDescriptor PERMISSION_TREE_ELEMENT;
/** Private package attribute for the manifest element. Needs to be handled manually. */
- private static final TextAttributeDescriptor PACKAGE_ATTR_DESC;
+ private final TextAttributeDescriptor PACKAGE_ATTR_DESC;
- static {
+ public AndroidManifestDescriptors() {
APPLICATION_ELEMENT = createElement("application", null, true); //$NON-NLS-1$ + no child & mandatory
INTRUMENTATION_ELEMENT = createElement("instrumentation"); //$NON-NLS-1$
@@ -109,6 +110,46 @@ public class AndroidManifestDescriptors {
null /* nsUri */,
"This attribute gives a unique name for the package, using a Java-style naming convention to avoid name collisions.\nFor example, applications published by Google could have names of the form com.google.app.appname");
}
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { MANIFEST_ELEMENT };
+ }
+
+ public ElementDescriptor getDescriptor() {
+ return getManifestElement();
+ }
+
+ public ElementDescriptor getApplicationElement() {
+ return APPLICATION_ELEMENT;
+ }
+
+ public ElementDescriptor getManifestElement() {
+ return MANIFEST_ELEMENT;
+ }
+
+ public ElementDescriptor getUsesSdkElement() {
+ return USES_SDK_ELEMENT;
+ }
+
+ public ElementDescriptor getInstrumentationElement() {
+ return INTRUMENTATION_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionElement() {
+ return PERMISSION_ELEMENT;
+ }
+
+ public ElementDescriptor getUsesPermissionElement() {
+ return USES_PERMISSION_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionGroupElement() {
+ return PERMISSION_GROUP_ELEMENT;
+ }
+
+ public ElementDescriptor getPermissionTreeElement() {
+ return PERMISSION_TREE_ELEMENT;
+ }
/**
* Updates the document descriptor.
@@ -118,7 +159,7 @@ public class AndroidManifestDescriptors {
*
* @param manifestMap The map style => attributes from the attrs_manifest.xml file
*/
- public static synchronized void updateDescriptors(
+ public synchronized void updateDescriptors(
Map<String, DeclareStyleableInfo> manifestMap) {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
@@ -177,7 +218,7 @@ public class AndroidManifestDescriptors {
sanityCheck(manifestMap, MANIFEST_ELEMENT);
}
-
+
/**
* Sets up an attribute override for ANDROID_NAME_ATTR using a ClassAttributeDescriptor
* with the specified class name.
@@ -223,7 +264,7 @@ public class AndroidManifestDescriptors {
* <p/>
* Creates an element with no attribute overrides.
*/
- private static ElementDescriptor createElement(
+ private ElementDescriptor createElement(
String xmlName,
ElementDescriptor[] childrenElements,
boolean mandatory) {
@@ -243,7 +284,7 @@ public class AndroidManifestDescriptors {
* <p/>
* This version creates an element not mandatory.
*/
- private static ElementDescriptor createElement(String xmlName) {
+ private ElementDescriptor createElement(String xmlName) {
// Creates an element with no child and not mandatory
return createElement(xmlName, null, false);
}
@@ -253,7 +294,7 @@ public class AndroidManifestDescriptors {
* (based on the attribute XML name.)
* The attribute is inserted at the beginning of the attribute list.
*/
- private static void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
+ private void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
AttributeDescriptor[] attributes = element.getAttributes();
for (AttributeDescriptor attr : attributes) {
if (attr.getXmlLocalName().equals(newAttr.getXmlLocalName())) {
@@ -285,7 +326,7 @@ public class AndroidManifestDescriptors {
* @param styleName The name of the {@link ElementDescriptor} to inflate. Its XML local name
* will be guessed automatically from the style name.
*/
- private static void inflateElement(
+ private void inflateElement(
Map<String, DeclareStyleableInfo> styleMap,
Map<String, Object> overrides,
HashMap<String, ElementDescriptor> existingElementDescs,
@@ -343,7 +384,7 @@ public class AndroidManifestDescriptors {
* <p/>
* Capitalizes the first letter and replace non-alphabet by a space followed by a capital.
*/
- private static String getUiName(String xmlName) {
+ private String getUiName(String xmlName) {
StringBuilder sb = new StringBuilder();
boolean capitalize = true;
@@ -376,7 +417,7 @@ public class AndroidManifestDescriptors {
* - application => AndroidManifestApplication
* - uses-permission => AndroidManifestUsesPermission
*/
- private static String guessStyleName(String xmlName) {
+ private String guessStyleName(String xmlName) {
StringBuilder sb = new StringBuilder();
if (!xmlName.equals(MANIFEST_NODE_NAME)) {
@@ -403,7 +444,7 @@ public class AndroidManifestDescriptors {
* manifestMap are actually defined in the actual element descriptors and reachable from
* the manifestElement root node.
*/
- private static void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
+ private void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
ElementDescriptor manifestElement) {
TreeSet<String> elementsDeclared = new TreeSet<String>();
findAllElementNames(manifestElement, elementsDeclared);
@@ -434,8 +475,8 @@ public class AndroidManifestDescriptors {
}
}
- EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
- EditorsPlugin.printToConsole(null, sb);
+ AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+ AdtPlugin.printToConsole((String)null, sb);
sb.setLength(0);
}
@@ -448,8 +489,8 @@ public class AndroidManifestDescriptors {
}
}
- EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
- EditorsPlugin.printToConsole(null, sb);
+ AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+ AdtPlugin.printToConsole((String)null, sb);
}
}
@@ -459,7 +500,7 @@ public class AndroidManifestDescriptors {
*
* @return The XML local name for a given style name.
*/
- private static String guessXmlName(String name) {
+ private String guessXmlName(String name) {
StringBuilder sb = new StringBuilder();
if (ANDROID_MANIFEST_STYLEABLE.equals(name)) {
sb.append(MANIFEST_NODE_NAME);
@@ -486,7 +527,7 @@ public class AndroidManifestDescriptors {
* <p/>
* Note: this assumes no circular reference in the tree of {@link ElementDescriptor}s.
*/
- private static void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
+ private void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
declared.add(element.getXmlName());
for (ElementDescriptor desc : element.getChildren()) {
findAllElementNames(desc, declared);
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
index eab7f09..eab7f09 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
index 1144006..1144006 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
index 6e589f7..6e589f7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
index d89292b..d89292b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
index 34c5d0d..34c5d0d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
index 3442c24..3442c24 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
index 5a8137d..5a8137d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
index 4219007..4219007 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
index f8aac1d..f8aac1d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
index 10ce50d..79295a8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
@@ -64,12 +64,15 @@ public final class UiManifestElementNode extends UiElementNode {
getXmlNode() instanceof Element &&
getXmlNode().hasAttributes()) {
+ AndroidManifestDescriptors manifestDescriptors =
+ getAndroidTarget().getManifestDescriptors();
+
// Application and Manifest nodes have a special treatment: they are unique nodes
// so we don't bother trying to differentiate their strings and we fall back to
// just using the UI name below.
ElementDescriptor desc = getDescriptor();
- if (desc != AndroidManifestDescriptors.MANIFEST_ELEMENT &&
- desc != AndroidManifestDescriptors.APPLICATION_ELEMENT) {
+ if (desc != manifestDescriptors.getManifestElement() &&
+ desc != manifestDescriptors.getApplicationElement()) {
Element elem = (Element) getXmlNode();
String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_NAME_ATTR);
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
index 5e02273..02fb44f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.manifest.model;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -184,7 +184,7 @@ public class UiPackageAttributeNode extends UiTextAttributeNode {
JavaCore.create(project), 0);
dlg.setTitle("Select Android Package");
dlg.setMessage("Select the package for the Android project.");
- dlg.setDefaultImage(EditorsPlugin.getAndroidLogo());
+ SelectionDialog.setDefaultImage(AdtPlugin.getAndroidLogo());
if (dlg.open() == Window.OK) {
Object[] results = dlg.getResult();
@@ -212,13 +212,13 @@ public class UiPackageAttributeNode extends UiTextAttributeNode {
IProject project = getProject();
if (project == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
return;
}
IWorkbenchPartSite site = getUiParent().getEditor().getSite();
if (site == null) {
- EditorsPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
return;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
index 25bdb0e..01b0f8f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -130,7 +130,7 @@ final class ApplicationAttributesPart extends UiElementPart {
} else {
// The XML has an extra attribute which wasn't declared in
// AndroidManifestDescriptors. This is not a problem, we just ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
uiElementNode.getDescriptor().getXmlName());
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
index 1823278..77527f0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -67,7 +67,7 @@ public final class ApplicationPage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Application");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode appUiNode = getUiApplicationNode();
@@ -96,8 +96,14 @@ public final class ApplicationPage extends FormPage {
* exists, even if there is no matching XML node.
*/
private UiElementNode getUiApplicationNode() {
- ElementDescriptor desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
- return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+ if (manifestDescriptor != null) {
+ ElementDescriptor desc = manifestDescriptor.getApplicationElement();
+ return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ } else {
+ // return the ui root node, as a dummy application root node.
+ return mEditor.getUiRootNode();
+ }
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
index daec98c..139575d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.ui.UiElementPart;
@@ -130,10 +130,10 @@ final class ApplicationToggle extends UiElementPart {
if (tooltip != null) {
tooltip = DescriptorsUtils.formatFormText(tooltip,
getUiElementNode().getDescriptor(),
- FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+ Sdk.getCurrent().getDocumentationBaseUrl());
mTooltipFormText.setText(tooltip, true /* parseTags */, true /* expandURLs */);
- mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, EditorsPlugin.getAndroidLogo());
+ mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, AdtPlugin.getAndroidLogo());
mTooltipFormText.addHyperlinkListener(getEditor().createHyperlinkListener());
isVisible = true;
}
@@ -156,23 +156,32 @@ final class ApplicationToggle extends UiElementPart {
public void widgetSelected(SelectionEvent e) {
super.widgetSelected(e);
if (!mInternalModification && getUiElementNode() != null) {
- getUiElementNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- if (mCheckbox.getSelection()) {
- // The user wants an <application> node. Either restore a previous one
- // or create a full new one.
- boolean create = true;
- if (mUndoXmlNode != null) {
- create = !restoreApplicationNode();
+ getUiElementNode().getEditor().wrapUndoRecording(
+ mCheckbox.getSelection()
+ ? "Create or restore Application node"
+ : "Remove Application node",
+ new Runnable() {
+ public void run() {
+ getUiElementNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ if (mCheckbox.getSelection()) {
+ // The user wants an <application> node.
+ // Either restore a previous one
+ // or create a full new one.
+ boolean create = true;
+ if (mUndoXmlNode != null) {
+ create = !restoreApplicationNode();
+ }
+ if (create) {
+ getUiElementNode().createXmlNode();
+ }
+ } else {
+ // Users no longer wants the <application> node.
+ removeApplicationNode();
+ }
+ }
+ });
}
- if (create) {
- getUiElementNode().createXmlNode();
- }
- } else {
- // Users no longer wants the <application> node.
- removeApplicationNode();
- }
- }
});
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
index 8eb6765..86d0dd1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -37,6 +37,8 @@ public final class InstrumentationPage extends FormPage {
/** Container editor */
ManifestEditor mEditor;
+ private UiTreeBlock mTreeBlock;
+
public InstrumentationPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Instrumentation"); // tab's label, keep it short
mEditor = editor;
@@ -52,14 +54,39 @@ public final class InstrumentationPage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Instrumentation");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode manifest = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ ElementDescriptor[] descriptorFilters = null;
+ if (manifestDescriptor != null) {
+ descriptorFilters = new ElementDescriptor[] {
+ manifestDescriptor.getInstrumentationElement(),
+ };
+ }
+
+ mTreeBlock = new UiTreeBlock(mEditor, manifest,
true /* autoCreateRoot */,
- new ElementDescriptor[] { AndroidManifestDescriptors.INTRUMENTATION_ELEMENT },
+ descriptorFilters,
"Instrumentation",
"List of instrumentations defined in the manifest");
- block.createContent(managedForm);
+ mTreeBlock.createContent(managedForm);
+ }
+
+ /**
+ * Changes and refreshes the Application UI node handled by the sub parts.
+ */
+ public void refreshUiNode() {
+ if (mTreeBlock != null) {
+ UiElementNode manifest = mEditor.getUiRootNode();
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ mTreeBlock.changeRootAndDescriptors(manifest,
+ new ElementDescriptor[] {
+ manifestDescriptor.getInstrumentationElement()
+ },
+ true /* refresh */);
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
index 4e6521c..66af84c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
@@ -49,9 +49,12 @@ final class OverviewExportPart extends ManifestSectionPart {
StringBuffer buf = new StringBuffer();
buf.append("<form><li><a href=\"wizard\">"); //$NON-NLS-1$
- buf.append("Use the export wizard");
- buf.append("</a></li><li><a href=\"manual\">"); //$NON-NLS-1$
- buf.append("Export an unsigned apk");
+ buf.append("Use the Export Wizard");
+ buf.append("</a>"); //$NON-NLS-1$
+ buf.append(" to export and sign an APK");
+ buf.append("</li>"); //$NON-NLS-1$
+ buf.append("<li><a href=\"manual\">"); //$NON-NLS-1$
+ buf.append("Export an unsigned APK");
buf.append("</a>"); //$NON-NLS-1$
buf.append(" and sign it manually");
buf.append("</li></form>"); //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
index 182c6f3..026b760 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
@@ -49,12 +49,19 @@ final class OverviewInfoPart extends UiElementPart {
* and can't be null, by design, because it's a mandatory node.
*/
private static UiElementNode getManifestUiNode(ManifestEditor editor) {
- ElementDescriptor desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;
- if (editor.getUiRootNode().getDescriptor() == desc) {
- return editor.getUiRootNode();
- } else {
- return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+ if (manifestDescriptors != null) {
+ ElementDescriptor desc = manifestDescriptors.getManifestElement();
+ if (editor.getUiRootNode().getDescriptor() == desc) {
+ return editor.getUiRootNode();
+ } else {
+ return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ }
}
+
+ // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+ // The editor will be reloaded once we have the proper descriptors anyway.
+ return editor.getUiRootNode();
}
/**
@@ -62,8 +69,15 @@ final class OverviewInfoPart extends UiElementPart {
* exists, even if there is no matching XML node.
*/
private UiElementNode getUsesSdkUiNode(ManifestEditor editor) {
- ElementDescriptor desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
- return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+ if (manifestDescriptors != null) {
+ ElementDescriptor desc = manifestDescriptors.getUsesSdkElement();
+ return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+ }
+
+ // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+ // The editor will be reloaded once we have the proper descriptors anyway.
+ return editor.getUiRootNode();
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
index 7675fa2..d637a8f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -33,8 +33,12 @@ import org.eclipse.ui.forms.widgets.Section;
*/
final class OverviewLinksPart extends ManifestSectionPart {
+ private final ManifestEditor mEditor;
+ private FormText mFormText;
+
public OverviewLinksPart(Composite body, FormToolkit toolkit, ManifestEditor editor) {
super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */);
+ mEditor = editor;
Section section = getSection();
section.setText("Links");
section.setDescription("The content of the Android Manifest is made up of three sections. You can also edit the XML directly.");
@@ -75,13 +79,40 @@ final class OverviewLinksPart extends ManifestSectionPart {
buf.append("</li>"); //$NON-NLS-1$
buf.append("</form>"); //$NON-NLS-1$
- FormText text = createFormText(table, toolkit, true, buf.toString(),
+ mFormText = createFormText(table, toolkit, true, buf.toString(),
false /* setupLayoutData */);
- text.setImage("android_img", EditorsPlugin.getAndroidLogo());
- text.setImage("app_img", getIcon(AndroidManifestDescriptors.APPLICATION_ELEMENT));
- text.setImage("perm_img", getIcon(AndroidManifestDescriptors.PERMISSION_ELEMENT));
- text.setImage("inst_img", getIcon(AndroidManifestDescriptors.INTRUMENTATION_ELEMENT));
- text.addHyperlinkListener(editor.createHyperlinkListener());
+
+ AndroidManifestDescriptors manifestDescriptor = editor.getManifestDescriptors();
+
+ Image androidLogo = AdtPlugin.getAndroidLogo();
+ mFormText.setImage("android_img", androidLogo); //$NON-NLS-1$
+
+ if (manifestDescriptor != null) {
+ mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+ mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+ mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+ } else {
+ mFormText.setImage("app_img", androidLogo); //$NON-NLS-1$
+ mFormText.setImage("perm_img", androidLogo); //$NON-NLS-1$
+ mFormText.setImage("inst_img", androidLogo); //$NON-NLS-1$
+ }
+ mFormText.addHyperlinkListener(editor.createHyperlinkListener());
+ }
+
+ /**
+ * Update the UI with information from the new descriptors.
+ * <p/>At this point, this only refreshes the icons.
+ * <p/>
+ * This is called by {@link OverviewPage#refreshUiApplicationNode()} when the
+ * SDK has changed.
+ */
+ public void onSdkChanged() {
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+ if (manifestDescriptor != null) {
+ mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+ mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+ mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+ }
}
private Image getIcon(ElementDescriptor desc) {
@@ -89,6 +120,6 @@ final class OverviewLinksPart extends ManifestSectionPart {
return desc.getIcon();
}
- return EditorsPlugin.getAndroidLogo();
+ return AdtPlugin.getAndroidLogo();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
index 9e8925a..62954bd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import org.eclipse.swt.widgets.Composite;
@@ -43,6 +43,8 @@ public final class OverviewPage extends FormPage {
ManifestEditor mEditor;
/** Overview part (attributes for manifest) */
private OverviewInfoPart mOverviewPart;
+ /** Overview link part */
+ private OverviewLinksPart mOverviewLinkPart;
public OverviewPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Overview"); // tab's label, user visible, keep it short
@@ -59,7 +61,7 @@ public final class OverviewPage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Overview");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
Composite body = form.getBody();
FormToolkit toolkit = managedForm.getToolkit();
@@ -69,7 +71,8 @@ public final class OverviewPage extends FormPage {
mOverviewPart = new OverviewInfoPart(body, toolkit, mEditor);
managedForm.addPart(mOverviewPart);
managedForm.addPart(new OverviewExportPart(this, body, toolkit, mEditor));
- managedForm.addPart(new OverviewLinksPart(body, toolkit, mEditor));
+ mOverviewLinkPart = new OverviewLinksPart(body, toolkit, mEditor);
+ managedForm.addPart(mOverviewLinkPart);
}
/**
@@ -79,5 +82,9 @@ public final class OverviewPage extends FormPage {
if (mOverviewPart != null) {
mOverviewPart.onSdkChanged();
}
+
+ if (mOverviewLinkPart != null) {
+ mOverviewLinkPart.onSdkChanged();
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
index a7c0ad5..41ba22e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.manifest.pages;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -41,6 +41,8 @@ public final class PermissionPage extends FormPage {
/** Container editor */
ManifestEditor mEditor;
+ private UiTreeBlock mTreeBlock;
+
public PermissionPage(ManifestEditor editor) {
super(editor, PAGE_ID, "Permissions"); // tab label, keep it short
mEditor = editor;
@@ -56,19 +58,44 @@ public final class PermissionPage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Manifest Permissions");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode manifest = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ ElementDescriptor[] descriptorFilters = null;
+ if (manifestDescriptor != null) {
+ descriptorFilters = new ElementDescriptor[] {
+ manifestDescriptor.getPermissionElement(),
+ manifestDescriptor.getUsesPermissionElement(),
+ manifestDescriptor.getPermissionGroupElement(),
+ manifestDescriptor.getPermissionTreeElement()
+ };
+ }
+ mTreeBlock = new UiTreeBlock(mEditor, manifest,
true /* autoCreateRoot */,
- new ElementDescriptor[] {
- AndroidManifestDescriptors.PERMISSION_ELEMENT,
- AndroidManifestDescriptors.USES_PERMISSION_ELEMENT,
- AndroidManifestDescriptors.PERMISSION_GROUP_ELEMENT,
- AndroidManifestDescriptors.PERMISSION_TREE_ELEMENT
- },
+ descriptorFilters,
"Permissions",
"List of permissions defined and used by the manifest");
- block.createContent(managedForm);
+ mTreeBlock.createContent(managedForm);
+ }
+
+ /**
+ * Changes and refreshes the Application UI node handled by the sub parts.
+ */
+ public void refreshUiNode() {
+ if (mTreeBlock != null) {
+ UiElementNode manifest = mEditor.getUiRootNode();
+ AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+ mTreeBlock.changeRootAndDescriptors(manifest,
+ new ElementDescriptor[] {
+ manifestDescriptor.getPermissionElement(),
+ manifestDescriptor.getUsesPermissionElement(),
+ manifestDescriptor.getPermissionGroupElement(),
+ manifestDescriptor.getPermissionTreeElement()
+ },
+ true /* refresh */);
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
index 57b9a42..bf76d53 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.menu;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
/**
* Content Assist Processor for /res/menu XML files
@@ -28,6 +28,6 @@ class MenuContentAssist extends AndroidContentAssist {
* Constructor for LayoutContentAssist
*/
public MenuContentAssist() {
- super(MenuDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_MENU);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
index 4bf02fa..cff1746 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
@@ -16,11 +16,12 @@
package com.android.ide.eclipse.editors.menu;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import org.eclipse.core.resources.IFile;
@@ -40,19 +41,16 @@ import javax.xml.xpath.XPathExpressionException;
*/
public class MenuEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.menu.MenuEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".menu.MenuEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiElementNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/**
* Creates the form editor for resources XML files.
*/
public MenuEditor() {
super();
- initUiRootNode();
}
/**
@@ -66,15 +64,6 @@ public class MenuEditor extends AndroidEditor {
// ---- Base Class Overrides ----
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
- super.dispose();
- }
-
/**
* Returns whether the "save as" operation is supported by this editor.
* <p/>
@@ -96,7 +85,7 @@ public class MenuEditor extends AndroidEditor {
try {
addPage(new MenuTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
}
@@ -121,6 +110,9 @@ public class MenuEditor extends AndroidEditor {
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.setXmlDocument(xml_doc);
if (xml_doc != null) {
ElementDescriptor root_desc = mUiRootNode.getDescriptor();
@@ -139,38 +131,54 @@ public class MenuEditor extends AndroidEditor {
// TODO ? startMonitoringMarkers();
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
root_desc.getXmlName());
}
}
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- ElementDescriptor desc = MenuDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ ElementDescriptor desc;
+ if (data == null) {
+ desc = new ElementDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getMenuDescriptors().getDescriptor();
+ }
+
mUiRootNode = desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
+ onDescriptorsChanged(doc);
+ }
+ }
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ // ---- Local Methods ----
+
+ /**
+ * Reloads the UI manifest node from the XML, and calls the pages to update.
+ */
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
index a5e3b09..a5e3b09 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
index 994074e..edbfa5e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.menu;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -49,7 +49,7 @@ public final class MenuTreePage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Menu");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode rootNode = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
index 941f736..34c7bb2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
@@ -21,6 +21,7 @@ import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import java.util.ArrayList;
@@ -30,32 +31,22 @@ import java.util.Map;
/**
* Complete description of the menu structure.
*/
-public class MenuDescriptors {
+public final class MenuDescriptors implements IDescriptorProvider {
public static final String MENU_ROOT_ELEMENT = "menu"; //$NON-NLS-1$
-
-
- /** Singleton instance */
- private static MenuDescriptors sThis;
-
/** The root element descriptor. */
private ElementDescriptor mDescriptor = null;
- /** Returns a singleton instance of the {@link MenuDescriptors}. */
- public static synchronized MenuDescriptors getInstance() {
- if (sThis == null) {
- sThis = new MenuDescriptors();
- sThis.updateDescriptors(null);
- }
- return sThis;
- }
-
/** @return the root descriptor. */
public ElementDescriptor getDescriptor() {
return mDescriptor;
}
-
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
+ }
+
/**
* Updates the document descriptor.
* <p/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
index 9fe15ab..c9c8e17 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
@@ -16,9 +16,8 @@
package com.android.ide.eclipse.editors.resources;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
/**
* Content Assist Processor for /res/values and /res/drawable XML files
@@ -29,6 +28,6 @@ class ResourcesContentAssist extends AndroidContentAssist {
* Constructor for ResourcesContentAssist
*/
public ResourcesContentAssist() {
- super(new ElementDescriptor[] { ResourcesDescriptors.RESOURCES_ELEMENT });
+ super(AndroidTargetData.DESCRIPTOR_RESOURCES);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
index bad5699..46a9112 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.resources;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidXPathFactory;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -41,7 +42,7 @@ import javax.xml.xpath.XPathExpressionException;
*/
public class ResourcesEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.resources.ResourcesEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".resources.ResourcesEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiElementNode mUiResourcesNode;
@@ -52,7 +53,6 @@ public class ResourcesEditor extends AndroidEditor {
*/
public ResourcesEditor() {
super();
- initUiResourcesNode();
}
/**
@@ -87,8 +87,8 @@ public class ResourcesEditor extends AndroidEditor {
try {
addPage(new ResourcesTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
- EditorsPlugin.getDefault().getLog().log(e.getStatus());
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
}
}
@@ -113,9 +113,13 @@ public class ResourcesEditor extends AndroidEditor {
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiResourcesNode.setXmlDocument(xml_doc);
if (xml_doc != null) {
- ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;
+ ElementDescriptor resources_desc =
+ ResourcesDescriptors.getInstance().getElementDescriptor();
try {
XPath xpath = AndroidXPathFactory.newXPath();
Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(), //$NON-NLS-1$
@@ -126,27 +130,35 @@ public class ResourcesEditor extends AndroidEditor {
// Refresh the manifest UI node and all its descendants
mUiResourcesNode.loadFromXmlNode(node);
} catch (XPathExpressionException e) {
- EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
resources_desc.getXmlName());
}
}
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiResourcesNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The manifest UI node is always created, even if there's no corresponding XML node.
- if (mUiResourcesNode == null) {
- ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;
+ if (mUiResourcesNode == null || force) {
+ ElementDescriptor resources_desc =
+ ResourcesDescriptors.getInstance().getElementDescriptor();
mUiResourcesNode = resources_desc.createUiNode();
mUiResourcesNode.setEditor(this);
+
+ onDescriptorsChanged();
}
}
+ // ---- Local Methods ----
+
+ private void onDescriptorsChanged() {
+ // nothing to be done, as the descriptor are static for now.
+ // FIXME Update when the descriptors are not static
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
index 1804312..1804312 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
index 8cabeca..5c1b0e1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.resources;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
@@ -72,7 +72,7 @@ public final class ResourcesTreePage extends FormPage {
form.setText("Android Resources");
}
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode resources = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, resources,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
index 7670fa2..1d01260 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
@@ -92,7 +92,7 @@ public final class CountryCodeQualifier extends ResourceQualifier {
@Override
public Image getIcon() {
- return IconFactory.getInstance().getIcon("world"); //$NON-NLS-1$
+ return IconFactory.getInstance().getIcon("mcc"); //$NON-NLS-1$
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
index 3c3e11f..3c3e11f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
index ad232ed..ad232ed 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
index 99c3a43..99c3a43 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
index 1a2cf53..1a2cf53 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
index ce527a4..ce527a4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
index 0fd05bf..0fd05bf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
index dc4d5fa..dc4d5fa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
index 0257afa..0257afa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
index a2cc789..a2cc789 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
index e30930f..e30930f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
index de40138..de40138 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
index 2390e2c..2390e2c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
index 92288ba..92288ba 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
index bf83d52..bf83d52 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
index 4769cef..1075897 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
@@ -20,16 +20,16 @@ import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
/**
- * Complete description of the AndroidManifest.xml structure.
+ * Complete description of the structure for resources XML files (under res/values/)
*/
-public class ResourcesDescriptors {
-
+public class ResourcesDescriptors implements IDescriptorProvider {
// Public attributes names, attributes descriptors and elements descriptors
@@ -38,14 +38,33 @@ public class ResourcesDescriptors {
public static final String NAME_ATTR = "name"; //$NON-NLS-1$
public static final String TYPE_ATTR = "type"; //$NON-NLS-1$
- /** The {@link ElementDescriptor} for the root Manifest element. */
- public static final ElementDescriptor RESOURCES_ELEMENT;
-
+ private static final ResourcesDescriptors sThis = new ResourcesDescriptors();
+
+ /** The {@link ElementDescriptor} for the root Resources element. */
+ public final ElementDescriptor mResourcesElement;
- static {
+ public static ResourcesDescriptors getInstance() {
+ return sThis;
+ }
+
+ /*
+ * @see com.android.ide.eclipse.editors.descriptors.IDescriptorProvider#getRootElementDescriptors()
+ */
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { mResourcesElement };
+ }
+
+ public ElementDescriptor getDescriptor() {
+ return mResourcesElement;
+ }
+
+ public ElementDescriptor getElementDescriptor() {
+ return mResourcesElement;
+ }
+
+ private ResourcesDescriptors() {
// Common attributes used in many placed
-
// Elements
@@ -189,7 +208,61 @@ public class ResourcesDescriptors {
},
false /* not mandatory */);
- RESOURCES_ELEMENT = new ElementDescriptor(
+ ElementDescriptor string_array_element = new ElementDescriptor(
+ "string-array", //$NON-NLS-1$
+ "String Array",
+ "An array of strings. Strings are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(NAME_ATTR,
+ "Name*",
+ null /* nsUri */,
+ "The mandatory name used in referring to this string array."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ "item", //$NON-NLS-1$
+ "Item",
+ "A string value to use in this string array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory string.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ ElementDescriptor integer_array_element = new ElementDescriptor(
+ "integer-array", //$NON-NLS-1$
+ "Integer Array",
+ "An array of integers. Integers are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(NAME_ATTR,
+ "Name*",
+ null /* nsUri */,
+ "The mandatory name used in referring to this integer array."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ "item", //$NON-NLS-1$
+ "Item",
+ "An integer value to use in this integer array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory integer.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ mResourcesElement = new ElementDescriptor(
ROOT_ELEMENT,
"Resources",
null,
@@ -201,7 +274,9 @@ public class ResourcesDescriptors {
dimen_element,
drawable_element,
style_element,
- item_element
+ item_element,
+ string_array_element,
+ integer_array_element,
},
true /* mandatory */);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
index cc7bec8..845db32 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.resources.explorer;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.resources.manager.ProjectResourceItem;
import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
@@ -73,10 +73,12 @@ import java.util.Iterator;
public class ResourceExplorerView extends ViewPart implements ISelectionListener,
IResourceEventListener {
+ // Note: keep using the obsolete AndroidConstants.EDITORS_NAMESPACE (which used
+ // to be the Editors Plugin ID) to keep existing preferences functional.
private final static String PREFS_COLUMN_RES =
- AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col1"; //$NON-NLS-1$
+ AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col1"; //$NON-NLS-1$
private final static String PREFS_COLUMN_2 =
- AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col2"; //$NON-NLS-1$
+ AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col2"; //$NON-NLS-1$
private Tree mTree;
private TreeViewer mTreeViewer;
@@ -93,7 +95,7 @@ public class ResourceExplorerView extends ViewPart implements ISelectionListener
mTree.setHeaderVisible(true);
mTree.setLinesVisible(true);
- final IPreferenceStore store = EditorsPlugin.getDefault().getPreferenceStore();
+ final IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
// create 2 columns. The main one with the resources, and an "info" column.
createTreeColumn(mTree, "Resources", SWT.LEFT,
@@ -156,7 +158,7 @@ public class ResourceExplorerView extends ViewPart implements ISelectionListener
});
// set up the resource manager to send us resource change notification
- EditorsPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
+ AdtPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
index 366f4fd..455c825 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.resources.manager;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestHelper;
import com.android.ide.eclipse.common.resources.ResourceType;
@@ -124,24 +125,29 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi
ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */,
project);
- Class<?> clazz = loader.loadClass(className);
-
- if (clazz != null) {
- // create the maps to store the result of the parsing
- Map<String, Map<String, Integer>> resourceValueMap =
- new HashMap<String, Map<String, Integer>>();
- Map<Integer, String[]> genericValueToNameMap =
- new HashMap<Integer, String[]>();
- Map<IntArrayWrapper, String> styleableValueToNameMap =
- new HashMap<IntArrayWrapper, String>();
+ try {
+ Class<?> clazz = loader.loadClass(className);
- // parse the class
- if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
- resourceValueMap)) {
- // now we associate the maps to the project.
- projectResources.setCompiledResources(genericValueToNameMap,
- styleableValueToNameMap, resourceValueMap);
+ if (clazz != null) {
+ // create the maps to store the result of the parsing
+ Map<String, Map<String, Integer>> resourceValueMap =
+ new HashMap<String, Map<String, Integer>>();
+ Map<Integer, String[]> genericValueToNameMap =
+ new HashMap<Integer, String[]>();
+ Map<IntArrayWrapper, String> styleableValueToNameMap =
+ new HashMap<IntArrayWrapper, String>();
+
+ // parse the class
+ if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
+ resourceValueMap)) {
+ // now we associate the maps to the project.
+ projectResources.setCompiledResources(genericValueToNameMap,
+ styleableValueToNameMap, resourceValueMap);
+ }
}
+ } catch (Error e) {
+ // Log this error with the class name we're trying to load and abort.
+ AdtPlugin.log(e, "loadAndParseRClass failed to find class %1$s", className); //$NON-NLS-1$
}
}
} catch (ClassNotFoundException e) {
@@ -155,7 +161,7 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi
* @param genericValueToNameMap
* @param styleableValueToNameMap
* @param resourceValueMap
- * @return
+ * @return True if we managed to parse the R class.
*/
private boolean parseClass(Class<?> rClass, Map<Integer, String[]> genericValueToNameMap,
Map<IntArrayWrapper, String> styleableValueToNameMap, Map<String,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
index 57c17fc..57c17fc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
index a9f80bd..a9f80bd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
index 552aec9..552aec9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
index 25eb112..25eb112 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
index 72438a6..72438a6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
index 5658224..183af27 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
@@ -215,12 +215,6 @@ public final class ProjectClassLoader extends ClassLoader {
// get the IPath
IPath path = e.getPath();
- // get the file name. if it's the framework jar, we ignore that file.
- // since we now use classpath container, this is here for legacy purpose only.
- if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
- continue;
- }
-
// check the name ends with .jar
if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
boolean local = false;
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
index ba770b2..ba770b2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
index b0881fa..b0881fa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
index dd8d080..dd8d080 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
index f927a9a..f927a9a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
index 6db0d94..6db0d94 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
index bd93301..bd93301 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
index 64942ed..9c5f0fc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
@@ -29,6 +29,7 @@ import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFile;
import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder;
import com.android.ide.eclipse.editors.resources.manager.files.IFileWrapper;
import com.android.ide.eclipse.editors.resources.manager.files.IFolderWrapper;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -57,8 +58,6 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
private final HashMap<IProject, ProjectResources> mMap =
new HashMap<IProject, ProjectResources>();
- private ProjectResources mFrameworkResources = null;
-
/**
* Sets up the resource manager with the global resource monitor.
* @param monitor The global resource monitor
@@ -89,14 +88,6 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
}
/**
- * Returns the resources of the framework.
- * <p/>This could be <code>null</code> if the parsing failed.
- */
- public ProjectResources getFrameworkResources() {
- return mFrameworkResources;
- }
-
- /**
* Processes folder event.
*/
public void folderChanged(IFolder folder, int kind) {
@@ -277,24 +268,23 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
}
/**
- * Loads the framework resources.
+ * Loads and returns the resources for a given {@link IAndroidTarget}
* @param osFilePath the path to the folder containing all the versions of the framework
* resources
*/
- public void loadFrameworkResources(String osResourcesPath) {
- // for now only load the default framework resources
- osResourcesPath += AndroidConstants.FD_DEFAULT_RES;
+ public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
+ String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
File frameworkRes = new File(osResourcesPath);
if (frameworkRes.isDirectory()) {
- mFrameworkResources = new ProjectResources(true /* isFrameworkRepository */);
+ ProjectResources resources = new ProjectResources(true /* isFrameworkRepository */);
try {
File[] files = frameworkRes.listFiles();
for (File file : files) {
if (file.isDirectory()) {
ResourceFolder resFolder = processFolder(new FolderWrapper(file),
- mFrameworkResources);
+ resources);
if (resFolder != null) {
// now we process the content of the folder
@@ -311,13 +301,17 @@ public final class ResourceManager implements IProjectListener, IFolderListener,
}
// now that we have loaded the files, we need to force load the resources from them
- mFrameworkResources.loadAll();
+ resources.loadAll();
+
+ return resources;
} catch (IOException e) {
// since we test that folders are folders, and files are files, this shouldn't
// happen. We can ignore it.
}
}
+
+ return null;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
index 45a020c..dc0f505 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
@@ -257,6 +257,20 @@ public class ResourceMonitor implements IResourceChangeListener {
mFileListeners.add(bundle);
}
+
+ /**
+ * Removes an existing file listener.
+ * @param listener the listener to remove.
+ */
+ public synchronized void removeFileListener(IFileListener listener) {
+ for (int i = 0 ; i < mFileListeners.size() ; i++) {
+ FileListenerBundle bundle = mFileListeners.get(i);
+ if (bundle.listener == listener) {
+ mFileListeners.remove(i);
+ return;
+ }
+ }
+ }
/**
* Adds a folder listener.
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
index 1211236..1211236 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
index 0a14214..0a14214 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
index 8afea33..8afea33 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
index 7e807f9..7e807f9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
index b35283d..b35283d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
index daf243d..daf243d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
index 441c65b..441c65b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
index 92b5c07..92b5c07 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
index 29453e9..29453e9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
index 89649f5..89649f5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
index 5fb479f..5fb479f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
index d095376..d095376 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
index ccae099..ccae099 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
index 304dd14..304dd14 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
index 4fc0ab3..4fc0ab3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
index 7942024..409e92f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.swt.events.MouseEvent;
@@ -173,7 +173,7 @@ public final class SectionHelper {
reflow.setAccessible(true);
reflow.invoke(section);
} catch (Exception e) {
- EditorsPlugin.log(e, "Error when invoking Section.reflow");
+ AdtPlugin.log(e, "Error when invoking Section.reflow");
}
section.layout(true /* changed */, true /* all */);
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
index 2fe5783..2fe5783 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
index 69adebd..66773bd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.ui;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -60,7 +60,7 @@ public class UiElementPart extends ManifestSectionPart {
if (uiElementNode == null) {
// This is serious and should never happen. Instead of crashing, simply abort.
// There will be no UI, which will prevent further damage.
- EditorsPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
return;
}
}
@@ -222,7 +222,7 @@ public class UiElementPart extends ManifestSectionPart {
} else {
// The XML has an extra attribute which wasn't declared in
// AndroidManifestDescriptors. This is not a problem, we just ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
uiNode.getDescriptor().getXmlName());
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
new file mode 100644
index 0000000..2aad217
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 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.editors.ui.tree;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.document.NodeContainer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Provides Cut and Copy actions for the tree nodes.
+ */
+public class CopyCutAction extends Action {
+ private List<UiElementNode> mUiNodes;
+ private boolean mPerformCut;
+ private final AndroidEditor mEditor;
+ private final Clipboard mClipboard;
+ private final ICommitXml mXmlCommit;
+
+ /**
+ * Creates a new Copy or Cut action.
+ *
+ * @param selected The UI node to cut or copy. It *must* have a non-null XML node.
+ * @param perform_cut True if the operation is cut, false if it is copy.
+ */
+ public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+ UiElementNode selected, boolean perform_cut) {
+ this(editor, clipboard, xmlCommit, toList(selected), perform_cut);
+ }
+
+ /**
+ * Creates a new Copy or Cut action.
+ *
+ * @param selected The UI nodes to cut or copy. They *must* have a non-null XML node.
+ * The list becomes owned by the {@link CopyCutAction}.
+ * @param perform_cut True if the operation is cut, false if it is copy.
+ */
+ public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+ List<UiElementNode> selected, boolean perform_cut) {
+ super(perform_cut ? "Cut" : "Copy");
+ mEditor = editor;
+ mClipboard = clipboard;
+ mXmlCommit = xmlCommit;
+
+ ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
+ if (perform_cut) {
+ setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+ setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+ setDisabledImageDescriptor(
+ images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
+ } else {
+ setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+ setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+ setDisabledImageDescriptor(
+ images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
+ }
+
+ mUiNodes = selected;
+ mPerformCut = perform_cut;
+ }
+
+ /**
+ * Performs the cut or copy action.
+ * First an XML serializer is used to turn the existing XML node into a valid
+ * XML fragment, which is added as text to the clipboard.
+ */
+ @Override
+ public void run() {
+ super.run();
+ if (mUiNodes == null || mUiNodes.size() < 1) {
+ return;
+ }
+
+ // Commit the current pages first, to make sure the XML is in sync.
+ // Committing may change the XML structure.
+ if (mXmlCommit != null) {
+ mXmlCommit.commitPendingXmlChanges();
+ }
+
+ StringBuilder allText = new StringBuilder();
+ ArrayList<UiElementNode> nodesToCut = mPerformCut ? new ArrayList<UiElementNode>() : null;
+
+ for (UiElementNode uiNode : mUiNodes) {
+ try {
+ Node xml_node = uiNode.getXmlNode();
+ if (xml_node == null) {
+ return;
+ }
+
+ String data = getXmlTextFromEditor(xml_node);
+
+ // In the unlikely event that IStructuredDocument failed to extract the text
+ // directly from the editor, try to fall back on a direct XML serialization
+ // of the XML node. This uses the generic Node interface with no SSE tricks.
+ if (data == null) {
+ data = getXmlTextFromSerialization(xml_node);
+ }
+
+ if (data != null) {
+ allText.append(data);
+ if (mPerformCut) {
+ // only remove notes to cut if we actually got some XML text from them
+ nodesToCut.add(uiNode);
+ }
+ }
+
+ } catch (Exception e) {
+ AdtPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
+ uiNode.getBreadcrumbTrailDescription(true));
+ }
+ } // for uiNode
+
+ if (allText != null && allText.length() > 0) {
+ mClipboard.setContents(
+ new Object[] { allText.toString() },
+ new Transfer[] { TextTransfer.getInstance() });
+ if (mPerformCut) {
+ for (UiElementNode uiNode : nodesToCut) {
+ uiNode.deleteXmlNode();
+ }
+ }
+ }
+ }
+
+ /** Get the data directly from the editor. */
+ private String getXmlTextFromEditor(Node xml_node) {
+ String data = null;
+ IStructuredModel model = mEditor.getModelForRead();
+ try {
+ IStructuredDocument sse_doc = mEditor.getStructuredDocument();
+ if (xml_node instanceof NodeContainer) {
+ // The easy way to get the source of an SSE XML node.
+ data = ((NodeContainer) xml_node).getSource();
+ } else if (xml_node instanceof IndexedRegion && sse_doc != null) {
+ // Try harder.
+ IndexedRegion region = (IndexedRegion) xml_node;
+ int start = region.getStartOffset();
+ int end = region.getEndOffset();
+
+ if (end > start) {
+ data = sse_doc.get(start, end - start);
+ }
+ }
+ } catch (BadLocationException e) {
+ // the region offset was invalid. ignore.
+ } finally {
+ model.releaseFromRead();
+ }
+ return data;
+ }
+
+ /**
+ * Direct XML serialization of the XML node.
+ * <p/>
+ * This uses the generic Node interface with no SSE tricks. It's however slower
+ * and doesn't respect formatting (since serialization is involved instead of reading
+ * the actual text buffer.)
+ */
+ private String getXmlTextFromSerialization(Node xml_node) throws IOException {
+ String data;
+ StringWriter sw = new StringWriter();
+ XMLSerializer serializer = new XMLSerializer(sw,
+ new OutputFormat(Method.XML,
+ OutputFormat.Defaults.Encoding /* utf-8 */,
+ true /* indent */));
+ // Serialize will throw an IOException if it fails.
+ serializer.serialize((Element) xml_node);
+ data = sw.toString();
+ return data;
+ }
+
+ /**
+ * Static helper class to wrap on node into a list for the constructors.
+ */
+ private static ArrayList<UiElementNode> toList(UiElementNode selected) {
+ ArrayList<UiElementNode> list = null;
+ if (selected != null) {
+ list = new ArrayList<UiElementNode>(1);
+ list.add(selected);
+ }
+ return list;
+ }
+}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
index 8b6aa0e..8b6aa0e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
index 00e44ab..772fb52 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -90,19 +91,19 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
public IStatus validate(Object[] selection) {
if (selection.length == 1 && selection[0] instanceof ViewElementDescriptor) {
return new Status(IStatus.OK, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.OK, // code
((ViewElementDescriptor) selection[0]).getCanonicalClassName(), //msg
null); // exception
} else if (selection.length == 1 && selection[0] instanceof ElementDescriptor) {
return new Status(IStatus.OK, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.OK, // code
"", //$NON-NLS-1$ // msg
null); // exception
} else {
return new Status(IStatus.ERROR, // severity
- AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+ AdtPlugin.PLUGIN_ID, //plugin id
IStatus.ERROR, // code
"Invalid selection", // msg, translatable
null); // exception
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
index 68580b0..8bb4ad2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -113,7 +113,7 @@ public class PasteAction extends Action {
}
} catch (BadLocationException e) {
- EditorsPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
+ AdtPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
mUiNode.getBreadcrumbTrailDescription(true), data);
} finally {
model.releaseFromEdit();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
new file mode 100644
index 0000000..21180b1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 com.android.ide.eclipse.editors.ui.tree;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * Performs basic actions on an XML tree: add node, remove node, move up/down.
+ */
+public abstract class UiActions implements ICommitXml {
+
+ public UiActions() {
+ }
+
+ //---------------------
+ // Actual implementations must override these to provide specific hooks
+
+ /** Returns the UiDocumentNode for the current model. */
+ abstract protected UiElementNode getRootNode();
+
+ /** Commits pending data before the XML model is modified. */
+ abstract public void commitPendingXmlChanges();
+
+ /**
+ * Utility method to select an outline item based on its model node
+ *
+ * @param uiNode The node to select. Can be null (in which case nothing should happen)
+ */
+ abstract protected void selectUiNode(UiElementNode uiNode);
+
+ //---------------------
+
+ /**
+ * Called when the "Add..." button next to the tree view is selected.
+ * <p/>
+ * This simplified version of doAdd does not support descriptor filters and creates
+ * a new {@link UiModelTreeLabelProvider} for each call.
+ */
+ public void doAdd(UiElementNode uiNode, Shell shell) {
+ doAdd(uiNode, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
+ }
+
+ /**
+ * Called when the "Add..." button next to the tree view is selected.
+ *
+ * Displays a selection dialog that lets the user select which kind of node
+ * to create, depending on the current selection.
+ */
+ public void doAdd(UiElementNode uiNode,
+ ElementDescriptor[] descriptorFilters,
+ Shell shell, ILabelProvider labelProvider) {
+ // If the root node is a document with already a root, use it as the root node
+ UiElementNode rootNode = getRootNode();
+ if (rootNode instanceof UiDocumentNode && rootNode.getUiChildren().size() > 0) {
+ rootNode = rootNode.getUiChildren().get(0);
+ }
+
+ NewItemSelectionDialog dlg = new NewItemSelectionDialog(
+ shell,
+ labelProvider,
+ descriptorFilters,
+ uiNode, rootNode);
+ dlg.open();
+ Object[] results = dlg.getResult();
+ if (results != null && results.length > 0) {
+ addElement(dlg.getChosenRootNode(), null, (ElementDescriptor) results[0],
+ true /*updateLayout*/);
+ }
+ }
+
+ /**
+ * Adds a new XML element based on the {@link ElementDescriptor} to the given parent
+ * {@link UiElementNode}, and then select it.
+ * <p/>
+ * If the parent is a document root which already contains a root element, the inner
+ * root element is used as the actual parent. This ensure you can't create a broken
+ * XML file with more than one root element.
+ * <p/>
+ * If a sibling is given and that sibling has the same parent, the new node is added
+ * right after that sibling. Otherwise the new node is added at the end of the parent
+ * child list.
+ *
+ * @param uiParent An existing UI node or null to add to the tree root
+ * @param uiSibling An existing UI node before which to insert the new node. Can be null.
+ * @param descriptor The descriptor of the element to add
+ * @param updateLayout True if layout attributes should be set
+ * @return The new {@link UiElementNode} or null.
+ */
+ public UiElementNode addElement(UiElementNode uiParent,
+ UiElementNode uiSibling,
+ ElementDescriptor descriptor,
+ boolean updateLayout) {
+ if (uiParent instanceof UiDocumentNode && uiParent.getUiChildren().size() > 0) {
+ uiParent = uiParent.getUiChildren().get(0);
+ }
+ if (uiSibling != null && uiSibling.getUiParent() != uiParent) {
+ uiSibling = null;
+ }
+
+ UiElementNode uiNew = addNewTreeElement(uiParent, uiSibling, descriptor, updateLayout);
+ selectUiNode(uiNew);
+
+ return uiNew;
+ }
+
+ /**
+ * Called when the "Remove" button is selected.
+ *
+ * If the tree has a selection, remove it.
+ * This simply deletes the XML node attached to the UI node: when the XML model fires the
+ * update event, the tree will get refreshed.
+ */
+ public void doRemove(final List<UiElementNode> nodes, Shell shell) {
+
+ if (nodes == null || nodes.size() == 0) {
+ return;
+ }
+
+ final int len = nodes.size();
+
+ StringBuilder sb = new StringBuilder();
+ for (UiElementNode node : nodes) {
+ sb.append("\n- "); //$NON-NLS-1$
+ sb.append(node.getBreadcrumbTrailDescription(false /* include_root */));
+ }
+
+ if (MessageDialog.openQuestion(shell,
+ len > 1 ? "Remove elements from Android XML" // title
+ : "Remove element from Android XML",
+ String.format("Do you really want to remove %1$s?", sb.toString()))) {
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ UiElementNode previous = null;
+ UiElementNode parent = null;
+
+ for (int i = len - 1; i >= 0; i--) {
+ UiElementNode node = nodes.get(i);
+ previous = node.getUiPreviousSibling();
+ parent = node.getUiParent();
+
+ // delete node
+ node.deleteXmlNode();
+ }
+
+ // try to select the last previous sibling or the last parent
+ if (previous != null) {
+ selectUiNode(previous);
+ } else if (parent != null) {
+ selectUiNode(parent);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Called when the "Up" button is selected.
+ * <p/>
+ * If the tree has a selection, move it up, either in the child list or as the last child
+ * of the previous parent.
+ */
+ public void doUp(final List<UiElementNode> nodes) {
+ if (nodes == null || nodes.size() < 1) {
+ return;
+ }
+
+ final Node[] select_xml_node = { null };
+ UiElementNode last_node = null;
+ UiElementNode search_root = null;
+
+ for (int i = 0; i < nodes.size(); i++) {
+ final UiElementNode node = last_node = nodes.get(i);
+
+ // the node will move either up to its parent or grand-parent
+ search_root = node.getUiParent();
+ if (search_root != null && search_root.getUiParent() != null) {
+ search_root = search_root.getUiParent();
+ }
+
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ Node xml_node = node.getXmlNode();
+ if (xml_node != null) {
+ Node xml_parent = xml_node.getParentNode();
+ if (xml_parent != null) {
+ UiElementNode ui_prev = node.getUiPreviousSibling();
+ if (ui_prev != null && ui_prev.getXmlNode() != null) {
+ // This node is not the first one of the parent, so it can be
+ // removed and then inserted before its previous sibling.
+ // If the previous sibling can have children, though, then it
+ // is inserted at the end of the children list.
+ Node xml_prev = ui_prev.getXmlNode();
+ if (ui_prev.getDescriptor().hasChildren()) {
+ xml_prev.appendChild(xml_parent.removeChild(xml_node));
+ select_xml_node[0] = xml_node;
+ } else {
+ xml_parent.insertBefore(
+ xml_parent.removeChild(xml_node),
+ xml_prev);
+ select_xml_node[0] = xml_node;
+ }
+ } else if (!(xml_parent instanceof Document) &&
+ xml_parent.getParentNode() != null &&
+ !(xml_parent.getParentNode() instanceof Document)) {
+ // If the node is the first one of the child list of its
+ // parent, move it up in the hierarchy as previous sibling
+ // to the parent. This is only possible if the parent of the
+ // parent is not a document.
+ Node grand_parent = xml_parent.getParentNode();
+ grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_parent);
+ select_xml_node[0] = xml_node;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ if (select_xml_node[0] == null) {
+ // The XML node has not been moved, we can just select the same UI node
+ selectUiNode(last_node);
+ } else {
+ // The XML node has moved. At this point the UI model has been reloaded
+ // and the XML node has been affected to a new UI node. Find that new UI
+ // node and select it.
+ if (search_root == null) {
+ search_root = last_node.getUiRoot();
+ }
+ if (search_root != null) {
+ selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+ }
+ }
+ }
+
+ /**
+ * Called when the "Down" button is selected.
+ *
+ * If the tree has a selection, move it down, either in the same child list or as the
+ * first child of the next parent.
+ */
+ public void doDown(final List<UiElementNode> nodes) {
+ if (nodes == null || nodes.size() < 1) {
+ return;
+ }
+
+ final Node[] select_xml_node = { null };
+ UiElementNode last_node = null;
+ UiElementNode search_root = null;
+
+ for (int i = nodes.size() - 1; i >= 0; i--) {
+ final UiElementNode node = last_node = nodes.get(i);
+ // the node will move either down to its parent or grand-parent
+ search_root = node.getUiParent();
+ if (search_root != null && search_root.getUiParent() != null) {
+ search_root = search_root.getUiParent();
+ }
+
+ commitPendingXmlChanges();
+ getRootNode().getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ Node xml_node = node.getXmlNode();
+ if (xml_node != null) {
+ Node xml_parent = xml_node.getParentNode();
+ if (xml_parent != null) {
+ UiElementNode uiNext = node.getUiNextSibling();
+ if (uiNext != null && uiNext.getXmlNode() != null) {
+ // This node is not the last one of the parent, so it can be
+ // removed and then inserted after its next sibling.
+ // If the next sibling is a node that can have children, though,
+ // then the node is inserted as the first child.
+ Node xml_next = uiNext.getXmlNode();
+ if (uiNext.getDescriptor().hasChildren()) {
+ // Note: insertBefore works as append if the ref node is
+ // null, i.e. when the node doesn't have children yet.
+ xml_next.insertBefore(xml_parent.removeChild(xml_node),
+ xml_next.getFirstChild());
+ select_xml_node[0] = xml_node;
+ } else {
+ // Insert "before after next" ;-)
+ xml_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_next.getNextSibling());
+ select_xml_node[0] = xml_node;
+ }
+ } else if (!(xml_parent instanceof Document) &&
+ xml_parent.getParentNode() != null &&
+ !(xml_parent.getParentNode() instanceof Document)) {
+ // This node is the last node of its parent.
+ // If neither the parent nor the grandparent is a document,
+ // then the node can be insert right after the parent.
+ Node grand_parent = xml_parent.getParentNode();
+ grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+ xml_parent.getNextSibling());
+ select_xml_node[0] = xml_node;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ if (select_xml_node[0] == null) {
+ // The XML node has not been moved, we can just select the same UI node
+ selectUiNode(last_node);
+ } else {
+ // The XML node has moved. At this point the UI model has been reloaded
+ // and the XML node has been affected to a new UI node. Find that new UI
+ // node and select it.
+ if (search_root == null) {
+ search_root = last_node.getUiRoot();
+ }
+ if (search_root != null) {
+ selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+ }
+ }
+ }
+
+ //---------------------
+
+ /**
+ * Adds a new element of the given descriptor's type to the given UI parent node.
+ *
+ * This actually creates the corresponding XML node in the XML model, which in turn
+ * will refresh the current tree view.
+ *
+ * @param uiParent An existing UI node or null to add to the tree root
+ * @param uiSibling An existing UI node to insert right before. Can be null.
+ * @param descriptor The descriptor of the element to add
+ * @param updateLayout True if layout attributes should be set
+ * @return The {@link UiElementNode} that has been added to the UI tree.
+ */
+ private UiElementNode addNewTreeElement(UiElementNode uiParent,
+ final UiElementNode uiSibling,
+ ElementDescriptor descriptor,
+ final boolean updateLayout) {
+ commitPendingXmlChanges();
+
+ int index = 0;
+ for (UiElementNode uiChild : uiParent.getUiChildren()) {
+ if (uiChild == uiSibling) {
+ break;
+ }
+ index++;
+ }
+
+ final UiElementNode uiNew = uiParent.insertNewUiChild(index, descriptor);
+ UiElementNode rootNode = getRootNode();
+
+ rootNode.getEditor().editXmlModel(new Runnable() {
+ public void run() {
+ DescriptorsUtils.setDefaultLayoutAttributes(uiNew, updateLayout);
+ Node xmlNode = uiNew.createXmlNode();
+ }
+ });
+ return uiNew;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
index 010e30e..15c67c3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
@@ -16,14 +16,14 @@
package com.android.ide.eclipse.editors.ui.tree;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
@@ -130,7 +130,7 @@ class UiElementDetail implements IDetailsPage {
// Finally reset the dirty flag if everything was saved properly
mIsDirty = false;
} catch (Exception e) {
- EditorsPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
} finally {
// Notify the model we're done modifying it. This must *always* be executed.
model.changedModel();
@@ -260,9 +260,15 @@ class UiElementDetail implements IDetailsPage {
mCurrentUiElementNode = ui_node;
if (elem_desc.getTooltip() != null) {
- String tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
- elem_desc,
- FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+ String tooltip;
+ if (Sdk.getCurrent() != null &&
+ Sdk.getCurrent().getDocumentationBaseUrl() != null) {
+ tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
+ elem_desc,
+ Sdk.getCurrent().getDocumentationBaseUrl());
+ } else {
+ tooltip = elem_desc.getTooltip();
+ }
try {
FormText text = SectionHelper.createFormText(masterTable, toolkit,
@@ -275,7 +281,7 @@ class UiElementDetail implements IDetailsPage {
} catch(Exception e) {
// The FormText parser is really really basic and will fail as soon as the
// HTML javadoc is ever so slightly malformatted.
- EditorsPlugin.log(e,
+ AdtPlugin.log(e,
"Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$
ui_node.getDescriptor().getXmlName(),
tooltip);
@@ -320,7 +326,7 @@ class UiElementDetail implements IDetailsPage {
} else {
// The XML has an extra unknown attribute.
// This is not expected to happen so it is ignored.
- EditorsPlugin.log(IStatus.INFO,
+ AdtPlugin.log(IStatus.INFO,
"Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
attr_desc.getXmlLocalName(),
ui_node.getDescriptor().getXmlName());
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
index 9f34d9e..9f34d9e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
index ff5f24c..273a30b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.ui.tree;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.ui.ErrorImageComposite;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -62,7 +62,7 @@ public class UiModelTreeLabelProvider implements ILabelProvider {
}
}
}
- return EditorsPlugin.getAndroidLogo();
+ return AdtPlugin.getAndroidLogo();
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
index 7e7bd68..e3255d9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.ui.tree;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -42,6 +42,7 @@ import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.DisposeEvent;
@@ -64,6 +65,8 @@ import org.eclipse.ui.forms.MasterDetailsBlock;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.LinkedList;
/**
@@ -117,9 +120,15 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
private IUiUpdateListener mUiRefreshListener;
/** Listener to enable/disable the UI based on the application node's presence */
private IUiUpdateListener mUiEnableListener;
-
+ /** An adapter/wrapper to use the add/remove/up/down tree edit actions. */
private UiTreeActions mUiTreeActions;
-
+ /**
+ * True if the root node can be created on-demand (i.e. as needed as
+ * soon as children exist). False if an external entity controls the existence of the
+ * root node. In practise, this is false for the manifest application page (the actual
+ * "application" node is managed by the ApplicationToggle part) whereas it is true
+ * for all other tree pages.
+ */
private final boolean mAutoCreateRoot;
@@ -192,10 +201,24 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
private void createSectionActions(Section section, FormToolkit toolkit) {
ToolBarManager manager = new ToolBarManager(SWT.FLAT);
+ manager.removeAll();
+
ToolBar toolbar = manager.createControl(section);
section.setTextClient(toolbar);
+ ElementDescriptor[] descs = mDescriptorFilters;
+ if (descs == null && mUiRootNode != null) {
+ descs = mUiRootNode.getDescriptor().getChildren();
+ }
+
+ if (descs != null && descs.length > 1) {
+ for (ElementDescriptor desc : descs) {
+ manager.add(new DescriptorFilterAction(desc));
+ }
+ }
+
manager.add(new TreeSortAction());
+
manager.update(true /*force*/);
}
@@ -207,7 +230,7 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
final IManagedForm managedForm) {
// Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here.
// However the class must be adapted to create an adapted toolkit tree.
- final Tree tree = toolkit.createTree(grid, SWT.SINGLE);
+ final Tree tree = toolkit.createTree(grid, SWT.MULTI);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = AndroidEditor.TEXT_WIDTH_HINT;
gd.heightHint = TREE_HEIGHT_HINT;
@@ -283,7 +306,7 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */);
// Listen on resource framework changes to refresh the tree
- EditorsPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
+ AdtPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
// Remove listeners when the tree widget gets disposed.
tree.addDisposeListener(new DisposeListener() {
@@ -295,7 +318,7 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
node.removeUpdateListener(mUiRefreshListener);
mUiRootNode.removeUpdateListener(mUiEnableListener);
- EditorsPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
+ AdtPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
if (mClipboard != null) {
mClipboard.dispose();
mClipboard = null;
@@ -350,6 +373,8 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
if (forceRefresh) {
mTreeViewer.refresh();
}
+
+ createSectionActions(mMasterPart.getSection(), mManagedForm.getToolkit());
}
/**
@@ -426,13 +451,9 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
public void menuAboutToShow(IMenuManager manager) {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first != null && first instanceof UiElementNode) {
- UiElementNode ui_node = (UiElementNode) first;
- doCreateMenuAction(manager, ui_node);
- return;
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ doCreateMenuAction(manager, selected);
+ return;
}
doCreateMenuAction(manager, null /* ui_node */);
}
@@ -446,63 +467,78 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
* the tree view.
*
* @param manager The context menu manager
- * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+ * @param selected The UI nodes selected in the tree. Can be null, in which case the root
* is to be modified.
*/
- private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
- Action action;
-
- if (ui_node != null && ui_node.getXmlNode() != null) {
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- this, ui_node, true /* cut */));
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- this, ui_node, false /* cut */));
- // Paste is not valid if it would add a second element on a terminal element
- // which parent is a document -- an XML document can only have one child. This
- // means paste is valid if the current UI node can have children or if the parent
- // is not a document.
- if (mUiRootNode.getDescriptor().hasChildren() ||
- !(mUiRootNode.getUiParent() instanceof UiDocumentNode)) {
- manager.add(new PasteAction(getEditor(), getClipboard(), ui_node));
+ private void doCreateMenuAction(IMenuManager manager, ArrayList<UiElementNode> selected) {
+ if (selected != null) {
+ boolean hasXml = false;
+ for (UiElementNode uiNode : selected) {
+ if (uiNode.getXmlNode() != null) {
+ hasXml = true;
+ break;
+ }
+ }
+
+ if (hasXml) {
+ manager.add(new CopyCutAction(getEditor(), getClipboard(),
+ null, selected, true /* cut */));
+ manager.add(new CopyCutAction(getEditor(), getClipboard(),
+ null, selected, false /* cut */));
+
+ // Can't paste with more than one element selected (the selection is the target)
+ if (selected.size() <= 1) {
+ // Paste is not valid if it would add a second element on a terminal element
+ // which parent is a document -- an XML document can only have one child. This
+ // means paste is valid if the current UI node can have children or if the
+ // parent is not a document.
+ UiElementNode ui_root = selected.get(0).getUiRoot();
+ if (ui_root.getDescriptor().hasChildren() ||
+ !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+ manager.add(new PasteAction(getEditor(), getClipboard(), selected.get(0)));
+ }
+ }
+ manager.add(new Separator());
}
- manager.add(new Separator());
}
// Append "add" and "remove" actions. They do the same thing as the add/remove
// buttons on the side.
-
- manager.add(new Action("Add...", EditorsPlugin.getAndroidLogoDesc()) {
- @Override
- public void run() {
- super.run();
- doTreeAdd();
- }
- });
-
- if (ui_node != null) {
- manager.add(new Action("Remove", EditorsPlugin.getAndroidLogoDesc()) {
+ Action action;
+ IconFactory factory = IconFactory.getInstance();
+
+ // "Add" makes sense only if there's 0 or 1 item selected since the
+ // one selected item becomes the target.
+ if (selected == null || selected.size() <= 1) {
+ manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
- doTreeRemove();
+ doTreeAdd();
}
});
}
-
- manager.add(new Separator());
- if (ui_node != null) {
- manager.add(new Action("Up", EditorsPlugin.getAndroidLogoDesc()) {
+ if (selected != null) {
+ if (selected != null) {
+ manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-1$
+ @Override
+ public void run() {
+ super.run();
+ doTreeRemove();
+ }
+ });
+ }
+ manager.add(new Separator());
+
+ manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
doTreeUp();
}
});
- }
-
- if (ui_node != null) {
- manager.add(new Action("Down", EditorsPlugin.getAndroidLogoDesc()) {
+ manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-1$
@Override
public void run() {
super.run();
@@ -555,6 +591,27 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
}
/**
+ * Filters an ITreeSelection to only keep the {@link UiElementNode}s (in case there's
+ * something else in there).
+ *
+ * @return A new list of {@link UiElementNode} with at least one item or null.
+ */
+ @SuppressWarnings("unchecked")
+ private ArrayList<UiElementNode> filterSelection(ITreeSelection selection) {
+ ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+ for (Iterator it = selection.iterator(); it.hasNext(); ) {
+ Object selectedObj = it.next();
+
+ if (selectedObj instanceof UiElementNode) {
+ selected.add((UiElementNode) selectedObj);
+ }
+ }
+
+ return selected.size() > 0 ? selected : null;
+ }
+
+ /**
* Called when the "Add..." button next to the tree view is selected.
*
* Displays a selection dialog that lets the user select which kind of node
@@ -588,16 +645,11 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
protected void doTreeRemove() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doRemove(ui_node, mTreeViewer.getControl().getShell());
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doRemove(selected, mTreeViewer.getControl().getShell());
}
}
-
+
/**
* Called when the "Up" button is selected.
* <p/>
@@ -607,13 +659,8 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
protected void doTreeUp() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doUp(ui_node);
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doUp(selected);
}
}
@@ -626,13 +673,8 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
protected void doTreeDown() {
ISelection selection = mTreeViewer.getSelection();
if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- final UiElementNode ui_node = (UiElementNode) first;
-
- mUiTreeActions.doDown(ui_node);
- }
+ ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+ mUiTreeActions.doDown(selected);
}
}
@@ -653,7 +695,7 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
@Override
protected void createToolBarActions(IManagedForm managedForm) {
- // pass
+ // Pass. Not used, toolbar actions are defined by createSectionActions().
}
@Override
@@ -686,14 +728,14 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
}
/**
- * Adds a sort action to the tree viewer.
+ * An alphabetic sort action for the tree viewer.
*/
private class TreeSortAction extends Action {
private ViewerComparator mComparator;
public TreeSortAction() {
- setToolTipText("Sorts elements alphabetically.");
+ super("Sorts elements alphabetically.", AS_CHECK_BOX);
setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$
if (mTreeViewer != null) {
@@ -703,7 +745,7 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
}
/**
- * Called when the button is selected. Toggle the tree viewer comparator.
+ * Called when the button is selected. Toggles the tree viewer comparator.
*/
@Override
public void run() {
@@ -730,4 +772,97 @@ public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml
notifyResult(true /*success*/);
}
}
+
+ /**
+ * A filter on descriptor for the tree viewer.
+ * <p/>
+ * The tree viewer will contain many of these actions and only one can be enabled at a
+ * given time. When no action is selected, everything is displayed.
+ * <p/>
+ * Since "radio"-like actions do not allow for unselecting all of them, we manually
+ * handle the exclusive radio button-like property: when an action is selected, it manually
+ * removes all other actions as needed.
+ */
+ private class DescriptorFilterAction extends Action {
+
+ private final ElementDescriptor mDescriptor;
+ private ViewerFilter mFilter;
+
+ public DescriptorFilterAction(ElementDescriptor descriptor) {
+ super(String.format("Displays only %1$s elements.", descriptor.getUiName()),
+ AS_CHECK_BOX);
+
+ mDescriptor = descriptor;
+ setImageDescriptor(descriptor.getImageDescriptor());
+ }
+
+ /**
+ * Called when the button is selected.
+ * <p/>
+ * Find any existing {@link DescriptorFilter}s and remove them. Install ours.
+ */
+ @Override
+ public void run() {
+ super.run();
+
+ if (isChecked()) {
+ if (mFilter == null) {
+ // create filter when required
+ mFilter = new DescriptorFilter(this);
+ }
+
+ // we add our filter first, otherwise the UI might show the full list
+ mTreeViewer.addFilter(mFilter);
+
+ // Then remove the any other filters except ours. There should be at most
+ // one other filter, since that's how the actions are made to look like
+ // exclusive radio buttons.
+ for (ViewerFilter filter : mTreeViewer.getFilters()) {
+ if (filter instanceof DescriptorFilter && filter != mFilter) {
+ DescriptorFilterAction action = ((DescriptorFilter) filter).getAction();
+ action.setChecked(false);
+ mTreeViewer.removeFilter(filter);
+ }
+ }
+ } else if (mFilter != null){
+ mTreeViewer.removeFilter(mFilter);
+ }
+ }
+
+ /**
+ * Filters the tree viewer for the given descriptor.
+ * <p/>
+ * The filter is linked to the action so that an action can iterate through the list
+ * of filters and un-select the actions.
+ */
+ private class DescriptorFilter extends ViewerFilter {
+
+ private final DescriptorFilterAction mAction;
+
+ public DescriptorFilter(DescriptorFilterAction action) {
+ mAction = action;
+ }
+
+ public DescriptorFilterAction getAction() {
+ return mAction;
+ }
+
+ /**
+ * Returns true if an element should be displayed, that if the element or
+ * any of its parent matches the requested descriptor.
+ */
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ while (element instanceof UiElementNode) {
+ UiElementNode uiNode = (UiElementNode)element;
+ if (uiNode.getDescriptor() == mDescriptor) {
+ return true;
+ }
+ element = uiNode.getUiParent();
+ }
+ return false;
+ }
+ }
+ }
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
index 4c368d9..7fe44da 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
@@ -26,7 +26,7 @@ public interface IUiSettableAttributeNode {
/** Returns the current value of the node. */
public String getCurrentValue();
- /** Sets the current value of the node. */
+ /** Sets the current value of the node. Cannot be null (use an empty string). */
public void setCurrentValue(String value);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
index 12cb31b..12cb31b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
index 17b077a..5908574 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
@@ -37,7 +37,7 @@ public abstract class UiAbstractTextAttributeNode extends UiAttributeNode
/** Prevent internal listener from firing when internally modifying the text */
private boolean mInternalTextModification;
- /** Last value read from the XML model */
+ /** Last value read from the XML model. Cannot be null. */
private String mCurrentValue = DEFAULT_VALUE;
public UiAbstractTextAttributeNode(AttributeDescriptor attributeDescriptor,
@@ -51,7 +51,7 @@ public abstract class UiAbstractTextAttributeNode extends UiAttributeNode
return mCurrentValue;
}
- /** Sets the current value of the node. */
+ /** Sets the current value of the node. Cannot be null (use an empty string). */
public final void setCurrentValue(String value) {
mCurrentValue = value;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
index 5972f22..5972f22 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
index 113738f..113738f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
index 22b68b3..e0e9a40 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.uimodel;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
@@ -29,6 +30,7 @@ import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.ui.IEditorInput;
@@ -206,6 +208,10 @@ public class UiElementNode implements IPropertySource {
AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
}
if (attr == null || attr.length() == 0) {
+ attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
+ XmlDescriptors.PREF_KEY_ATTR);
+ }
+ if (attr == null || attr.length() == 0) {
attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR);
}
if (attr == null || attr.length() == 0) {
@@ -426,6 +432,13 @@ public class UiElementNode implements IPropertySource {
public AndroidEditor getEditor() {
return mUiParent == null ? mEditor : mUiParent.getEditor();
}
+
+ /**
+ * Returns the Android target data for the file being edited.
+ */
+ public AndroidTargetData getAndroidTarget() {
+ return getEditor().getTargetData();
+ }
/**
* @return A read-only version of the children collection.
@@ -447,7 +460,7 @@ public class UiElementNode implements IPropertySource {
}
return mReadOnlyUiAttributes;
}
-
+
/**
* @return A read-only version of the unknown attributes collection.
*/
@@ -564,7 +577,7 @@ public class UiElementNode implements IPropertySource {
return null;
}
-
+
/**
* Returns the {@link UiAttributeNode} matching this attribute descriptor or
* null if not found.
@@ -719,7 +732,16 @@ public class UiElementNode implements IPropertySource {
}
mXmlNode = doc.createElement(element_name);
- parentXmlNode.appendChild(mXmlNode);
+
+ Node xmlNextSibling = null;
+
+ UiElementNode uiNextSibling = getUiNextSibling();
+ if (uiNextSibling != null) {
+ xmlNextSibling = uiNextSibling.getXmlNode();
+ }
+
+ parentXmlNode.insertBefore(mXmlNode, xmlNextSibling);
+
// Insert a separator after the tag, to make it easier to read
Text sep = doc.createTextNode("\n");
parentXmlNode.appendChild(sep);
@@ -736,7 +758,7 @@ public class UiElementNode implements IPropertySource {
attr.setPrefix(desc.getXmlNsPrefix());
mXmlNode.getAttributes().setNamedItemNS(attr);
} else {
- UiAttributeNode ui_attr = mUiAttributes.get(attr_desc);
+ UiAttributeNode ui_attr = getInternalUiAttributes().get(attr_desc);
commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
}
}
@@ -873,7 +895,7 @@ public class UiElementNode implements IPropertySource {
false /* recursive */);
if (desc == null) {
// Unknown element. Simply ignore it.
- EditorsPlugin.log(IStatus.WARNING,
+ AdtPlugin.log(IStatus.WARNING,
"AndroidManifest: Ignoring unknown '%s' XML element", //$NON-NLS-1$
element_name);
} else {
@@ -953,7 +975,7 @@ public class UiElementNode implements IPropertySource {
* @param descriptor The {@link ElementDescriptor} that knows how to create the UI node.
* @return The new UI node.
*/
- private UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
+ public UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
UiElementNode ui_node;
ui_node = descriptor.createUiNode();
mUiChildren.add(index, ui_node);
@@ -1064,7 +1086,7 @@ public class UiElementNode implements IPropertySource {
listener.uiElementNodeUpdated(this, state);
} catch (Exception e) {
// prevent a crashing listener from crashing the whole invocation chain
- EditorsPlugin.log(e, "UIElement Listener failed: %s, state=%s", //$NON-NLS-1$
+ AdtPlugin.log(e, "UIElement Listener failed: %s, state=%s", //$NON-NLS-1$
getBreadcrumbTrailDescription(true),
state.toString());
}
@@ -1112,6 +1134,8 @@ public class UiElementNode implements IPropertySource {
* Note that the caller MUST ensure that modifying the underlying XML model is
* safe and must take care of marking the model as dirty if necessary.
*
+ * @see AndroidEditor#editXmlModel(Runnable)
+ *
* @param uiAttr The attribute node to commit. Must be a child of this UiElementNode.
* @param newValue The new value to set.
* @return True if the XML attribute was modified or removed, false if nothing changed.
@@ -1119,7 +1143,7 @@ public class UiElementNode implements IPropertySource {
public boolean commitAttributeToXml(UiAttributeNode uiAttr, String newValue) {
// Get (or create) the underlying XML element node that contains the attributes.
Node element = prepareCommit();
- if (element != null) {
+ if (element != null && uiAttr != null) {
String attrLocalName = uiAttr.getDescriptor().getXmlLocalName();
String attrNsUri = uiAttr.getDescriptor().getNamespaceUri();
@@ -1146,6 +1170,36 @@ public class UiElementNode implements IPropertySource {
}
/**
+ * Helper method to commit all dirty attributes values to XML.
+ * <p/>
+ * This method is useful if {@link #setAttributeValue(String, String, boolean)} has been
+ * called more than once and all the attributes marked as dirty must be commited to the
+ * XML. It calls {@link #commitAttributeToXml(UiAttributeNode, String)} on each dirty
+ * attribute.
+ * <p/>
+ * Note that the caller MUST ensure that modifying the underlying XML model is
+ * safe and must take care of marking the model as dirty if necessary.
+ *
+ * @see AndroidEditor#editXmlModel(Runnable)
+ *
+ * @return True if one or more values were actually modified or removed,
+ * false if nothing changed.
+ */
+ public boolean commitDirtyAttributesToXml() {
+ boolean result = false;
+ HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
+
+ for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
+ UiAttributeNode ui_attr = entry.getValue();
+ if (ui_attr.isDirty()) {
+ result |= commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
+ ui_attr.setDirty(false);
+ }
+ }
+ return result;
+ }
+
+ /**
* Returns the namespace prefix matching the requested namespace URI.
* If no such declaration is found, returns the default "android" prefix.
*
@@ -1226,13 +1280,21 @@ public class UiElementNode implements IPropertySource {
* This does not commit to the XML model. It does mark the attribute node as dirty.
* This is up to the caller.
*
+ * @see #commitAttributeToXml(UiAttributeNode, String)
+ * @see #commitDirtyAttributesToXml()
+ *
* @param attrXmlName The XML name of the attribute to modify
- * @param value The new value for the attribute.
+ * @param value The new value for the attribute. If set to null, the attribute is removed.
* @param override True if the value must be set even if one already exists.
+ * @return The {@link UiAttributeNode} that has been modified or null.
*/
- public void setAttributeValue(String attrXmlName, String value, boolean override) {
+ public UiAttributeNode setAttributeValue(String attrXmlName, String value, boolean override) {
HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
+ if (value == null) {
+ value = ""; //$NON-NLS-1$ -- this removes an attribute
+ }
+
for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
AttributeDescriptor ui_desc = entry.getKey();
if (ui_desc.getXmlLocalName().equals(attrXmlName)) {
@@ -1240,16 +1302,20 @@ public class UiElementNode implements IPropertySource {
// Not all attributes are editable, ignore those which are not
if (ui_attr instanceof IUiSettableAttributeNode) {
String current = ui_attr.getCurrentValue();
- if (override || current == null || current.length() == 0) {
+ // Only update (and mark as dirty) if the attribute did not have any
+ // value or if the value was different.
+ if (override || current == null || !current.equals(value)) {
((IUiSettableAttributeNode) ui_attr).setCurrentValue(value);
// mark the attribute as dirty since their internal content
// as been modified, but not the underlying XML model
ui_attr.setDirty(true);
+ return ui_attr;
}
}
break;
}
}
+ return null;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
index 4e0a8c7..ddcf0a0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
@@ -16,7 +16,8 @@
package com.android.ide.eclipse.editors.uimodel;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
@@ -138,8 +139,13 @@ public class UiFlagAttributeNode extends UiTextAttributeNode {
}
if (values == null) {
- // or from the framework resource manager
- values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name);
+ // or from the AndroidTargetData
+ UiElementNode uiNode = getUiParent();
+ AndroidEditor editor = uiNode.getEditor();
+ AndroidTargetData data = editor.getTargetData();
+ if (data != null) {
+ values = data.getAttributeValues(element_name, attr_name);
+ }
}
return values;
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
index 261e146..aaad0ce 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
@@ -16,9 +16,10 @@
package com.android.ide.eclipse.editors.uimodel;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
@@ -110,7 +111,7 @@ public class UiListAttributeNode extends UiAbstractTextAttributeNode {
String[] values = getPossibleValues();
if (values == null) {
- EditorsPlugin.log(IStatus.ERROR,
+ AdtPlugin.log(IStatus.ERROR,
"FrameworkResourceManager did not provide values yet for %1$s",
getDescriptor().getXmlLocalName());
} else {
@@ -150,21 +151,27 @@ public class UiListAttributeNode extends UiAbstractTextAttributeNode {
}
if (values == null) {
- // or from the framework resource manager
- // get the great-grand-parent descriptor.
-
- // the parent should always exist.
- UiElementNode grandParentNode = uiParent.getUiParent();
-
- String greatGrandParentNodeName = null;
- if (grandParentNode != null) {
- UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
- if (greatGrandParentNode != null) {
- greatGrandParentNodeName = greatGrandParentNode.getDescriptor().getXmlName();
+ // or from the AndroidTargetData
+ UiElementNode uiNode = getUiParent();
+ AndroidEditor editor = uiNode.getEditor();
+ AndroidTargetData data = editor.getTargetData();
+ if (data != null) {
+ // get the great-grand-parent descriptor.
+
+ // the parent should always exist.
+ UiElementNode grandParentNode = uiParent.getUiParent();
+
+ String greatGrandParentNodeName = null;
+ if (grandParentNode != null) {
+ UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
+ if (greatGrandParentNode != null) {
+ greatGrandParentNodeName =
+ greatGrandParentNode.getDescriptor().getXmlName();
+ }
}
+
+ values = data.getAttributeValues(element_name, attr_name, greatGrandParentNodeName);
}
- values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name,
- greatGrandParentNodeName);
}
return values;
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
index 132ccc0..1c1e1bd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.uimodel;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.editors.AndroidEditor;
@@ -28,7 +28,6 @@ import com.android.ide.eclipse.editors.ui.SectionHelper;
import com.android.ide.eclipse.editors.wizards.ReferenceChooserDialog;
import com.android.ide.eclipse.editors.wizards.ResourceChooser;
-import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
@@ -41,8 +40,6 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;
@@ -118,22 +115,19 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
* containing the result.
*/
public String showDialog(Shell shell, String currentValue) {
- // we need to get the project of the manifest.
+ // we need to get the project of the file being edited.
UiElementNode uiNode = getUiParent();
AndroidEditor editor = uiNode.getEditor();
- IEditorInput input = editor.getEditorInput();
- if (input instanceof IFileEditorInput) {
- // from the file editor we can get the IFile object, and from it, the IProject.
- IFile file = ((IFileEditorInput)input).getFile();
- IProject project = file.getProject();
-
+ IProject project = editor.getProject();
+ if (project != null) {
// get the resource repository for this project and the system resources.
IResourceRepository projectRepository =
ResourceManager.getInstance().getProjectResources(project);
if (mType != null) {
- IResourceRepository systemRepository =
- FrameworkResourceManager.getInstance().getSystemResources();
+ // get the Target Data to get the system resources
+ AndroidTargetData data = editor.getTargetData();
+ IResourceRepository systemRepository = data.getSystemResources();
// open a resource chooser dialog for specified resource type.
ResourceChooser dlg = new ResourceChooser(mType,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
index 192f752..192f752 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
index 4c53f4c..4c53f4c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
index 5c1db05..5c1db05 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
index 39cfc58..b7dffdd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
@@ -604,6 +604,8 @@ public class ConfigurationSelector extends Composite {
onTextChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(3 digit code)");
}
private void onTextChange() {
@@ -666,6 +668,8 @@ public class ConfigurationSelector extends Composite {
onTextChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(1-3 digit code)");
}
private void onTextChange() {
@@ -731,6 +735,8 @@ public class ConfigurationSelector extends Composite {
onLanguageChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(2 letter code)");
}
private void onLanguageChange() {
@@ -797,6 +803,8 @@ public class ConfigurationSelector extends Composite {
onRegionChange();
}
});
+
+ new Label(this, SWT.NONE).setText("(2 letter code)");
}
private void onRegionChange() {
@@ -1236,11 +1244,8 @@ public class ConfigurationSelector extends Composite {
String size1 = mSize1.getText();
String size2 = mSize2.getText();
- // if only one of the strings is empty, do nothing
- if ((size1.length() == 0) ^ (size2.length() == 0)) {
- return;
- } else if (size1.length() == 0 && size2.length() == 0) {
- // empty size, means no qualifier.
+ if (size1.length() == 0 || size2.length() == 0) {
+ // if one of the strings is empty, reset to no qualifier.
// Since the qualifier classes are immutable, and we don't want to
// remove the qualifier from the configuration, we create a new default one.
mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier());
@@ -1251,9 +1256,11 @@ public class ConfigurationSelector extends Composite {
if (qualifier != null) {
mSelectedConfiguration.setScreenDimensionQualifier(qualifier);
} else {
- // Failure! Looks like the value is wrong.
- // we do nothing in this case.
- return;
+ // Failure! Looks like the value is wrong, reset the qualifier
+ // Since the qualifier classes are immutable, and we don't want to
+ // remove the qualifier from the configuration, we create a new default one.
+ mSelectedConfiguration.setScreenDimensionQualifier(
+ new ScreenDimensionQualifier());
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
index 2f3209b..b27dd4f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
@@ -17,18 +17,19 @@
package com.android.ide.eclipse.editors.wizards;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier;
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -184,7 +185,7 @@ class NewXmlFileCreationPage extends WizardPage {
"Layout", // UI name
"An XML file that describes a screen layout.", // tooltip
ResourceFolderType.LAYOUT, // folder type
- LayoutDescriptors.getInstance().getDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_LAYOUT, // root seed
"LinearLayout", // default root
AndroidConstants.NS_RESOURCES, // xmlns
"android:layout_width=\"wrap_content\"\n" + // default attributes
@@ -209,7 +210,7 @@ class NewXmlFileCreationPage extends WizardPage {
new TypeInfo("Preference", // UI name
"An XML file that describes preferences.", // tooltip
ResourceFolderType.XML, // folder type
- XmlDescriptors.getInstance().getPreferencesDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_PREFERENCES, // root seed
AndroidConstants.CLASS_PREFERENCE_SCREEN, // default root
AndroidConstants.NS_RESOURCES, // xmlns
null // default attributes
@@ -217,7 +218,7 @@ class NewXmlFileCreationPage extends WizardPage {
new TypeInfo("Searchable", // UI name
"An XML file that describes a searchable [TODO].", // tooltip
ResourceFolderType.XML, // folder type
- XmlDescriptors.getInstance().getSearchableDescriptor(), // root seed
+ AndroidTargetData.DESCRIPTOR_SEARCHABLE, // root seed
null, // default root
AndroidConstants.NS_RESOURCES, // xmlns
null // default attributes
@@ -431,6 +432,11 @@ class NewXmlFileCreationPage extends WizardPage {
mProjectTextField = new Text(parent, SWT.BORDER);
mProjectTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mProjectTextField.setToolTipText(tooltip);
+ mProjectTextField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ onProjectFieldUpdated();
+ }
+ });
mProjectBrowseButton = new Button(parent, SWT.NONE);
mProjectBrowseButton.setText("Browse...");
@@ -655,9 +661,10 @@ class NewXmlFileCreationPage extends WizardPage {
*/
private void initializeRootValues() {
for (TypeInfo type : sTypes) {
+ // Clear all the roots for this type
ArrayList<String> roots = type.getRoots();
if (roots.size() > 0) {
- continue;
+ roots.clear();
}
// depending of the type of the seed, initialize the root in different ways
@@ -671,13 +678,22 @@ class NewXmlFileCreationPage extends WizardPage {
for (String value : (String[]) rootSeed) {
roots.add(value);
}
- } else if (rootSeed instanceof ElementDescriptor) {
- // The seed is an element descriptor or a document descriptor.
+ } else if (rootSeed instanceof Integer && mProject != null) {
+ // The seed is a descriptor reference defined in AndroidTargetData.DESCRIPTOR_*
// In this case add all the children element descriptors defined, recursively,
// and avoid infinite recursion by keeping track of what has already been added.
+
+ // Note: if project is null, the root list will be empty since it has been
+ // cleared above.
+
+ // get the AndroidTargetData from the project
+ IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ ElementDescriptor descriptor = data.getDescriptorProvider(
+ (Integer)rootSeed).getDescriptor();
HashSet<ElementDescriptor> visited = new HashSet<ElementDescriptor>();
- initRootElementDescriptor(roots, (ElementDescriptor) rootSeed, visited);
+ initRootElementDescriptor(roots, descriptor, visited);
// Sort alphabetically.
Collections.sort(roots);
@@ -708,6 +724,35 @@ class NewXmlFileCreationPage extends WizardPage {
}
}
}
+
+ /**
+ * Callback called when the user edits the project text field.
+ */
+ private void onProjectFieldUpdated() {
+ String project = mProjectTextField.getText();
+
+ // Is this a valid project?
+ IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null /*javaModel*/);
+ IProject found = null;
+ for (IJavaProject p : projects) {
+ if (p.getProject().getName().equals(project)) {
+ found = p.getProject();
+ break;
+ }
+ }
+
+ if (found != mProject) {
+ mProject = found;
+
+ // update the Type with the new descriptors.
+ initializeRootValues();
+
+ // update the combo
+ updateRootCombo(getSelectedType());
+
+ validatePage();
+ }
+ }
/**
* Callback called when the user uses the "Browse Projects" button.
@@ -717,6 +762,13 @@ class NewXmlFileCreationPage extends WizardPage {
if (p != null) {
mProject = p.getProject();
mProjectTextField.setText(mProject.getName());
+
+ // update the Type with the new descriptors.
+ initializeRootValues();
+
+ // update the combo
+ updateRootCombo(getSelectedType());
+
validatePage();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
index 8318e4b..125102b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
@@ -18,7 +18,7 @@
package com.android.ide.eclipse.editors.wizards;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.wizards.NewXmlFileCreationPage.TypeInfo;
@@ -116,7 +116,7 @@ public class NewXmlFileWizard extends Wizard implements INewWizard {
try {
IDE.openEditor(page, file);
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$
+ AdtPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$
file.getFullPath().toString());
}
}
@@ -133,7 +133,7 @@ public class NewXmlFileWizard extends Wizard implements INewWizard {
boolean need_delete = false;
if (file.exists()) {
- if (!EditorsPlugin.displayPrompt("New Android XML File",
+ if (!AdtPlugin.displayPrompt("New Android XML File",
String.format("Do you want to overwrite the file %1$s ?", name))) {
// abort if user selects cancel.
return null;
@@ -146,14 +146,14 @@ public class NewXmlFileWizard extends Wizard implements INewWizard {
TypeInfo type = mMainPage.getSelectedType();
if (type == null) {
// this is not expected to happen
- EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name); //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name); //$NON-NLS-1$
return null;
}
String xmlns = type.getXmlns();
String root = mMainPage.getRootElement();
if (root == null) {
// this is not expected to happen
- EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
+ AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
file.toString());
return null;
}
@@ -191,7 +191,7 @@ public class NewXmlFileWizard extends Wizard implements INewWizard {
}
error = String.format("Failed to generate %1$s: %2$s", name, error);
- EditorsPlugin.displayError("New Android XML File", error);
+ AdtPlugin.displayError("New Android XML File", error);
return null;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
index 446cc14..d3ff334 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.wizards;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -187,16 +188,16 @@ public class ReferenceChooserDialog extends SelectionStatusDialog {
IStatus status;
if (treeSelection != null) {
if (treeSelection.getSegmentCount() == 2) {
- status = new Status(IStatus.OK, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID,
IStatus.OK, "", //$NON-NLS-1$
null);
} else {
- status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
IStatus.ERROR, "You must select a Resource Item",
null);
}
} else {
- status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
IStatus.ERROR, "", //$NON-NLS-1$
null);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
index 60a627b..60a627b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
index 7c6a539..7c6a539 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
index 024d084..024d084 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
index bb010e3..f28b523 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
@@ -16,8 +16,8 @@
package com.android.ide.eclipse.editors.xml;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
/**
* Content Assist Processor for /res/xml XML files
@@ -28,6 +28,6 @@ class XmlContentAssist extends AndroidContentAssist {
* Constructor for LayoutContentAssist
*/
public XmlContentAssist() {
- super(XmlDescriptors.getInstance().getDescriptor().getChildren());
+ super(AndroidTargetData.DESCRIPTOR_XML);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
index 40d655a..b1900ae 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
@@ -16,16 +16,19 @@
package com.android.ide.eclipse.editors.xml;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
import com.android.ide.eclipse.editors.FirstElementParser;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
@@ -37,19 +40,16 @@ import org.w3c.dom.Document;
*/
public class XmlEditor extends AndroidEditor {
- public static final String ID = "com.android.ide.eclipse.editors.xml.XmlEditor"; //$NON-NLS-1$
+ public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".xml.XmlEditor"; //$NON-NLS-1$
/** Root node of the UI element hierarchy */
private UiDocumentNode mUiRootNode;
- /** Listener to update the root node if the resource framework changes */
- private Runnable mResourceRefreshListener;
/**
* Creates the form editor for resources XML files.
*/
public XmlEditor() {
super();
- initUiRootNode();
}
/**
@@ -72,19 +72,25 @@ public class XmlEditor extends AndroidEditor {
* @return True if the {@link XmlEditor} can handle that file.
*/
public static boolean canHandleFile(IFile file) {
-
- FirstElementParser.Result result = FirstElementParser.parse(
- file.getLocation().toOSString(),
- AndroidConstants.NS_RESOURCES);
+ // we need the target of the file's project to access the descriptors.
+ IProject project = file.getProject();
+ IAndroidTarget target = Sdk.getCurrent().getTarget(project);
+ if (target != null) {
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
- if (result != null) {
- String name = result.getElement();
- if (name != null && result.getXmlnsPrefix() != null) {
- DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
- for (ElementDescriptor elem : desc.getChildren()) {
- if (elem.getXmlName().equals(name)) {
- // This is an element that this document can handle
- return true;
+ FirstElementParser.Result result = FirstElementParser.parse(
+ file.getLocation().toOSString(),
+ AndroidConstants.NS_RESOURCES);
+
+ if (result != null) {
+ String name = result.getElement();
+ if (name != null && result.getXmlnsPrefix() != null) {
+ DocumentDescriptor desc = data.getXmlDescriptors().getDescriptor();
+ for (ElementDescriptor elem : desc.getChildren()) {
+ if (elem.getXmlName().equals(name)) {
+ // This is an element that this document can handle
+ return true;
+ }
}
}
}
@@ -95,15 +101,6 @@ public class XmlEditor extends AndroidEditor {
// ---- Base Class Overrides ----
- @Override
- public void dispose() {
- if (mResourceRefreshListener != null) {
- EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener = null;
- }
- super.dispose();
- }
-
/**
* Returns whether the "save as" operation is supported by this editor.
* <p/>
@@ -125,10 +122,10 @@ public class XmlEditor extends AndroidEditor {
try {
addPage(new XmlTreePage(this));
} catch (PartInitException e) {
- EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
}
- }
+ }
/* (non-java doc)
* Change the tab/title name to include the project name.
@@ -150,35 +147,55 @@ public class XmlEditor extends AndroidEditor {
*/
@Override
protected void xmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ initUiRootNode(false /*force*/);
+
mUiRootNode.loadFromXmlNode(xml_doc);
super.xmlModelChanged(xml_doc);
}
-
- // ---- Local Methods ----
-
/**
* Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
*/
- private void initUiRootNode() {
+ @Override
+ protected void initUiRootNode(boolean force) {
// The root UI node is always created, even if there's no corresponding XML node.
- if (mUiRootNode == null) {
- DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
+ if (mUiRootNode == null || force) {
+ Document doc = null;
+ if (mUiRootNode != null) {
+ doc = mUiRootNode.getXmlDocument();
+ }
+
+ // get the target data from the opened file (and its project)
+ AndroidTargetData data = getTargetData();
+
+ DocumentDescriptor desc;
+ if (data == null) {
+ desc = new DocumentDescriptor("temp", null /*children*/);
+ } else {
+ desc = data.getXmlDescriptors().getDescriptor();
+ }
+
mUiRootNode = (UiDocumentNode) desc.createUiNode();
mUiRootNode.setEditor(this);
- // Add a listener to refresh the root node if the resource framework changes
- // by forcing it to parse its own XML
- mResourceRefreshListener = new Runnable() {
- public void run() {
- commitPages(false /* onSave */);
+ onDescriptorsChanged(doc);
+ }
+ }
+
+ // ---- Local Methods ----
- mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
- mResourceRefreshListener.run();
+ /**
+ * Reloads the UI manifest node from the XML, and calls the pages to update.
+ */
+ private void onDescriptorsChanged(Document document) {
+ if (document != null) {
+ mUiRootNode.loadFromXmlNode(document);
+ } else {
+ mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
}
}
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
index d25c812..d25c812 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
index 5bb0f72..91ce6dd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
@@ -16,7 +16,7 @@
package com.android.ide.eclipse.editors.xml;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -49,7 +49,7 @@ public final class XmlTreePage extends FormPage {
super.createFormContent(managedForm);
ScrolledForm form = managedForm.getForm();
form.setText("Android Xml");
- form.setImage(EditorsPlugin.getAndroidLogo());
+ form.setImage(AdtPlugin.getAndroidLogo());
UiElementNode rootNode = mEditor.getUiRootNode();
UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
index 14cb9d6..31b4c61 100644
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
@@ -24,6 +24,7 @@ import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -36,10 +37,11 @@ import java.util.Map;
* Description of the /res/xml structure.
* Currently supports the <searchable> and <preferences> root nodes.
*/
-public class XmlDescriptors {
+public final class XmlDescriptors implements IDescriptorProvider {
- /** Singleton instance */
- private static XmlDescriptors sThis;
+ // Public attributes names, attributes descriptors and elements descriptors referenced
+ // elsewhere.
+ public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$
/** The root document descriptor for both searchable and preferences. */
private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
@@ -50,19 +52,15 @@ public class XmlDescriptors {
/** The root document descriptor for preferences. */
private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$
- /** Returns a singleton instance of the {@link XmlDescriptors}. */
- public static synchronized XmlDescriptors getInstance() {
- if (sThis == null) {
- sThis = new XmlDescriptors();
- }
- return sThis;
- }
-
/** @return the root descriptor for both searchable and preferences. */
public DocumentDescriptor getDescriptor() {
return mDescriptor;
}
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mDescriptor.getChildren();
+ }
+
/** @return the root descriptor for searchable. */
public DocumentDescriptor getSearchableDescriptor() {
return mSearchDescriptor;
@@ -72,6 +70,30 @@ public class XmlDescriptors {
public DocumentDescriptor getPreferencesDescriptor() {
return mPrefDescriptor;
}
+
+ public IDescriptorProvider getSearchableProvider() {
+ return new IDescriptorProvider() {
+ public ElementDescriptor getDescriptor() {
+ return mSearchDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mSearchDescriptor.getChildren();
+ }
+ };
+ }
+
+ public IDescriptorProvider getPreferencesProvider() {
+ return new IDescriptorProvider() {
+ public ElementDescriptor getDescriptor() {
+ return mPrefDescriptor;
+ }
+
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return mPrefDescriptor.getChildren();
+ }
+ };
+ }
/**
* Updates the document descriptor.
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/.classpath b/eclipse/plugins/com.android.ide.eclipse.common/.classpath
deleted file mode 100644
index a7b3dc1..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="lib" path="androidprefs.jar"/>
- <classpathentry kind="lib" path="sdkstats.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/.project b/eclipse/plugins/com.android.ide.eclipse.common/.project
deleted file mode 100644
index 510efb7..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>common</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
deleted file mode 100644
index dad85a6..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,22 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Common Plugin
-Bundle-SymbolicName: com.android.ide.eclipse.common;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .,
- sdkstats.jar,
- androidprefs.jar
-Bundle-Vendor: The Android Open Source Project
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.common,
- com.android.ide.eclipse.common.project,
- com.android.ide.eclipse.common.resources
-Require-Bundle: org.eclipse.core.resources,
- org.eclipse.core.runtime,
- org.eclipse.jdt.core,
- org.eclipse.ui.console,
- org.eclipse.ui,
- org.eclipse.jdt.ui,
- org.eclipse.jface.text,
- org.eclipse.ui.editors
-Bundle-Activator: com.android.ide.eclipse.common.CommonPlugin
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL b/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/NOTICE b/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/build.properties b/eclipse/plugins/com.android.ide.eclipse.common/build.properties
deleted file mode 100644
index 4c9981d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/build.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- sdkstats.jar,\
- plugin.xml,\
- androidprefs.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
deleted file mode 100644
index 115eb97..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- id="com.android.ide.eclipse.common.xmlProblem"
- name="XML Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.aaptProblem"
- name="aapt Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.aidlProblem"
- name="aidl Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- id="com.android.ide.eclipse.common.androidProblem"
- name="Android Problem"
- point="org.eclipse.core.resources.markers">
- <super type="org.eclipse.core.resources.problemmarker"/>
- <super type="org.eclipse.core.resources.textmarker"/>
- <persistent value="true"/>
- </extension>
- <extension
- point="org.eclipse.ui.preferencePages">
- <page
- category="com.android.ide.eclipse.preferences.main"
- class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
- id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
- name="Usage Stats"/>
- </extension>
-</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java b/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
deleted file mode 100644
index cfee50f..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2008 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.common;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.console.ConsolePlugin;
-import org.eclipse.ui.console.IConsole;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class CommonPlugin extends AbstractUIPlugin {
-
- // The plug-in ID
- public static final String PLUGIN_ID = "com.android.ide.eclipse.common"; // $NON-NLS-1$
-
- // The shared instance
- private static CommonPlugin sPlugin;
-
- // The global android console
- private MessageConsole mAndroidConsole;
-
- /**
- * The constructor
- */
- public CommonPlugin() {
- // pass
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static CommonPlugin getDefault() {
- return sPlugin;
- }
-
- /** Returns the global android console */
- public MessageConsole getAndroidConsole() {
- return mAndroidConsole;
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method refreshes the plug-in actions. Subclasses may extend this method,
- * but must send super <b>first</b>.
- *
- * {@inheritDoc}
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- sPlugin = this;
-
- /*
- * WARNING: think before adding any initialization here as plugins are dynamically
- * started and since no UI is being displayed by this plugin, it'll only start when
- * another plugin accesses some of its code.
- */
-
- // set the default android console.
- mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
- ConsolePlugin.getDefault().getConsoleManager().addConsoles(
- new IConsole[] { mAndroidConsole });
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method saves this plug-in's preference and dialog stores and shuts down
- * its image registry (if they are in use). Subclasses may extend this
- * method, but must send super <b>last</b>. A try-finally statement should
- * be used where necessary to ensure that <code>super.shutdown()</code> is
- * always done.
- *
- * {@inheritDoc}
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- super.stop(context);
- }
-
- /**
- * Logs a message to the default Eclipse log.
- *
- * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(int severity, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(severity, PLUGIN_ID, message);
- getDefault().getLog().log(status);
- }
-
- /**
- * Logs an exception to the default Eclipse log.
- * <p/>
- * The status severity is always set to ERROR.
- *
- * @param exception The exception to log. Its call trace will be recorded.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(Throwable exception, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
- getDefault().getLog().log(status);
- }
-
- private static Display getDisplay() {
- IWorkbench bench = sPlugin.getWorkbench();
- if (bench!=null) {
- return bench.getDisplay();
- }
- return null;
- }
-
- /**
- * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
- * therefore this message can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- * @return true if OK was clicked.
- */
- public final static boolean displayPrompt(final String title, final String message) {
- // get the current Display and Shell
- final Display display = getDisplay();
-
- // we need to ask the user what he wants to do.
- final Boolean[] wrapper = new Boolean[] { new Boolean(false) };
- display.syncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- wrapper[0] = new Boolean(MessageDialog.openQuestion(shell, title, message));
- }
- });
- return wrapper[0].booleanValue();
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
deleted file mode 100644
index 3f8f029..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 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.common.resources;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Map;
-
-/**
- * This is a communication between different plugins that don't know each other. It allows one
- * plugin to provide detailed information about the framework resources to another plugin.
- */
-public class FrameworkResourceManager {
-
- private static String[] sBooleanValues = new String[] {
- "true", //$NON-NLS-1$
- "false", //$NON-NLS-1$
- };
-
- private static FrameworkResourceManager sThis = new FrameworkResourceManager();
-
- private ArrayList<Runnable> mResourcesChangeListeners = new ArrayList<Runnable>();
-
- private Hashtable<String, String[]> mAttributeValues;
-
- private IResourceRepository mSystemResourceRepository;
-
- private ViewClassInfo[] mLayoutViewsInfo;
- private ViewClassInfo[] mLayoutGroupsInfo;
- private ViewClassInfo[] mPreferencesInfo;
- private ViewClassInfo[] mPreferenceGroupsInfo;
-
- private Map<String, DeclareStyleableInfo> mXmlMenuMap;
- private Map<String, DeclareStyleableInfo> mXmlSearchableMap;
- private Map<String, DeclareStyleableInfo> mManifestMap;
-
- /** Flags indicating whether we have some resources */
- private boolean mHasResources = false;
-
- private String mLayoutLibLocation;
-
- private String mFrameworkResourcesLocation;
-
- private Map<String, Map<String, Integer>> mEnumValueMap;
-
- private String mFrameworkFontsLocation;
-
- private String mDocBaseUrl;
-
- /**
- * Creates a new Framework Resource Manager.
- *
- * mAttributeValues is a map { key => list [ values ] }.
- * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
- * The attribute namespace prefix must be:
- * - "android" for AndroidConstants.NS_RESOURCES
- * - "xmlns" for the XMLNS URI.
- */
- private FrameworkResourceManager() {
- /* TODO Attempt to load those values from android.jar */
- mAttributeValues = new Hashtable<String, String[]>();
- mAttributeValues.put("(manifest,xmlns:android)", new String[] { //$NON-NLS-1$
- AndroidConstants.NS_RESOURCES
- });
- mAttributeValues.put("(permission,android:protectionLevel)", new String[] { //$NON-NLS-1$
- "application", //$NON-NLS-1$
- "system" //$NON-NLS-1$
- });
- mAttributeValues.put("(application,android:persistent)", new String[] { //$NON-NLS-1$
- "true", //$NON-NLS-1$
- "false", //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:clearOnBackground)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(activity,android:configChanges)", new String[] { //$NON-NLS-1$
- "fontScale", //$NON-NLS-1$
- "mcc", //$NON-NLS-1$
- "mnc", //$NON-NLS-1$
- "locale", //$NON-NLS-1$
- "touchscreen", //$NON-NLS-1$
- "keyboard", //$NON-NLS-1$
- "keyboardHidden", //$NON-NLS-1$
- "navigation", //$NON-NLS-1$
- "orientation", //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:launchMode)", new String[] { //$NON-NLS-1$
- "multiple", //$NON-NLS-1$
- "singleTop", //$NON-NLS-1$
- "singleTask", //$NON-NLS-1$
- "singleInstance" //$NON-NLS-1$
- });
- mAttributeValues.put("(activity,android:stateNotNeeded)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(provider,android:syncable)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(provider,android:multiprocess)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(instrumentation,android:functionalTest)", sBooleanValues); //$NON-NLS-1$
- mAttributeValues.put("(instrumentation,android:handleProfiling)", sBooleanValues); //$NON-NLS-1$
-
- }
-
- /**
- * Returns the {@link FrameworkResourceManager} instance.
- */
- public static FrameworkResourceManager getInstance() {
- return sThis;
- }
-
- /**
- * Sets the resources and notifies the listeners
- * @param documentationBaseUrl
- */
- public synchronized void setResources(IResourceRepository systemResourceRepository,
- ViewClassInfo[] layoutViewsInfo,
- ViewClassInfo[] layoutGroupsInfo,
- ViewClassInfo[] preferencesInfo,
- ViewClassInfo[] preferenceGroupsInfo,
- Map<String, DeclareStyleableInfo> xmlMenuMap,
- Map<String, DeclareStyleableInfo> xmlSearchableMap,
- Map<String, DeclareStyleableInfo> manifestMap,
- Map<String, Map<String, Integer>> enumValueMap,
- String[] permissionValues,
- String[] activityIntentActionValues,
- String[] broadcastIntentActionValues,
- String[] serviceIntentActionValues,
- String[] intentCategoryValues,
- String documentationBaseUrl) {
- mSystemResourceRepository = systemResourceRepository;
-
- mLayoutViewsInfo = layoutViewsInfo;
- mLayoutGroupsInfo = layoutGroupsInfo;
-
- mPreferencesInfo = preferencesInfo;
- mPreferenceGroupsInfo = preferenceGroupsInfo;
-
- mXmlMenuMap = xmlMenuMap;
- mXmlSearchableMap = xmlSearchableMap;
- mManifestMap = manifestMap;
- mEnumValueMap = enumValueMap;
- mDocBaseUrl = documentationBaseUrl;
-
- setPermissions(permissionValues);
- setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
- serviceIntentActionValues, intentCategoryValues);
-
- mHasResources = true;
-
- notifyFrameworkResourcesChangeListeners();
- }
-
- public synchronized IResourceRepository getSystemResources() {
- return mSystemResourceRepository;
- }
-
- public synchronized String[] getValues(String elementName, String attributeName) {
- String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
- return mAttributeValues.get(key);
- }
-
- public synchronized String[] getValues(String elementName, String attributeName,
- String greatGrandParentElementName) {
- if (greatGrandParentElementName != null) {
- String key = String.format("(%1$s,%2$s,%3$s)", greatGrandParentElementName, //$NON-NLS-1$
- elementName, attributeName);
- String[] values = mAttributeValues.get(key);
- if (values != null) {
- return values;
- }
- }
-
- return getValues(elementName, attributeName);
- }
-
- public synchronized String[] getValues(String key) {
- return mAttributeValues.get(key);
- }
-
- public synchronized ViewClassInfo[] getLayoutViewsInfo() {
- return mLayoutViewsInfo;
- }
-
- public synchronized ViewClassInfo[] getLayoutGroupsInfo() {
- return mLayoutGroupsInfo;
- }
-
- public synchronized ViewClassInfo[] getPreferencesInfo() {
- return mPreferencesInfo;
- }
-
- public synchronized ViewClassInfo[] getPreferenceGroupsInfo() {
- return mPreferenceGroupsInfo;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getXmlMenuDefinitions() {
- return mXmlMenuMap;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getXmlSearchableDefinitions() {
- return mXmlSearchableMap;
- }
-
- public synchronized Map<String, DeclareStyleableInfo> getManifestDefinitions() {
- return mManifestMap;
- }
-
- public String getDocumentationBaseUrl() {
- return mDocBaseUrl == null ? AndroidConstants.CODESITE_BASE_URL : mDocBaseUrl;
- }
-
- /**
- * Sets the permission values
- * @param permissionValues the list of permissions
- */
- private void setPermissions(String[] permissionValues) {
- setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
- setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
- setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
- }
-
- private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
- String[] broadcastIntentActions, String[] serviceIntentActions,
- String[] intentCategoryValues) {
- setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
- setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
- setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
- setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
- }
-
- /**
- * Sets a (name, values) pair in the hash map.
- * <p/>
- * If the name is already present in the map, it is first removed.
- * @param name the name associated with the values.
- * @param values The values to add.
- */
- private void setValues(String name, String[] values) {
- mAttributeValues.remove(name);
- mAttributeValues.put(name, values);
- }
-
-
- /**
- * Called by the ADT plugin when the SDK path has changed.
- * This stores the path locally and then notifies all attached listeners.
- */
- private void notifyFrameworkResourcesChangeListeners() {
- for (Runnable listener : mResourcesChangeListeners) {
- try {
- listener.run();
- } catch (Exception e) {
- CommonPlugin.log(e, "IPathChangedListener failed."); //$NON-NLS-1$
- }
- }
- }
-
- /** Adds a new listener that listens to framework resources changes.
- * <p/>If resources have already been set, then the listener is automatically notified. */
- public synchronized void addFrameworkResourcesChangeListener(Runnable listener) {
- if (listener != null && mResourcesChangeListeners.indexOf(listener) == -1) {
- mResourcesChangeListeners.add(listener);
-
- if (mHasResources) {
- listener.run();
- }
- }
- }
-
- /** Removes a framework resources changes listener.
- * <p/>Safe to call with null or with the same value. */
- public synchronized void removeFrameworkResourcesChangeListener(Runnable listener) {
- mResourcesChangeListeners.remove(listener);
- }
-
- public void setLayoutLibLocation(String osLocation) {
- mLayoutLibLocation = osLocation;
- }
-
- public String getLayoutLibLocation() {
- return mLayoutLibLocation;
- }
-
- public void setFrameworkResourcesLocation(String osLocation) {
- mFrameworkResourcesLocation = osLocation;
- }
-
- public String getFrameworkResourcesLocation() {
- return mFrameworkResourcesLocation;
- }
-
- public Map<String, Map<String, Integer>> getEnumValueMap() {
- return mEnumValueMap;
- }
-
- public void setFrameworkFontLocation(String osLocation) {
- mFrameworkFontsLocation = osLocation;
- }
-
- public String getFrameworkFontLocation() {
- return mFrameworkFontsLocation;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
index 2f315c5..09b8085 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Dalvik Debug Monitor Service
Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-Activator: com.android.ide.eclipse.ddms.DdmsPlugin
Bundle-Vendor: The Android Open Source Project
Bundle-Localization: plugin
@@ -10,11 +10,13 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.ui.console
Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.ddms.views,
- com.android.ddmlib,
+Export-Package: com.android.ddmlib,
+ com.android.ddmlib.log,
+ com.android.ddmlib.testrunner,
com.android.ddmuilib,
- com.android.ddmuilib.console
+ com.android.ddmuilib.console,
+ com.android.ide.eclipse.ddms,
+ com.android.ide.eclipse.ddms.views
Bundle-ClassPath: libs/jcommon-1.0.12.jar,
libs/jfreechart-1.0.9.jar,
libs/jfreechart-1.0.9-swt.jar,
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/.classpath b/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
deleted file mode 100644
index 66dbeb3..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
- <accessrules>
- <accessrule kind="accessible" pattern="org/eclipse/wst/**/internal/**"/>
- </accessrules>
- </classpathentry>
- <classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
- <classpathentry kind="lib" path="layoutlib_api.jar"/>
- <classpathentry kind="lib" path="ninepatch.jar"/>
- <classpathentry kind="lib" path="layoutlib_utils.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/.project b/eclipse/plugins/com.android.ide.eclipse.editors/.project
deleted file mode 100644
index 292c698..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>editors</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
deleted file mode 100644
index 0bfaff9..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,56 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Editors
-Bundle-SymbolicName: com.android.ide.eclipse.editors;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-Activator: com.android.ide.eclipse.editors.EditorsPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- org.eclipse.ui,
- org.eclipse.core.runtime,
- org.eclipse.core.resources,
- org.eclipse.ui.editors,
- org.eclipse.jface.text,
- org.eclipse.ui.ide,
- org.eclipse.wst.sse.ui,
- org.eclipse.wst.xml.ui,
- org.eclipse.wst.xml.core,
- org.eclipse.wst.sse.core,
- org.eclipse.ui.forms,
- org.eclipse.jdt.core,
- org.eclipse.ui.browser,
- org.eclipse.jdt.ui,
- org.eclipse.gef,
- org.eclipse.ui.views,
- org.eclipse.ui.console
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
-Bundle-ClassPath: kxml2-2.3.0.jar,
- .,
- layoutlib_api.jar,
- ninepatch.jar,
- layoutlib_utils.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL b/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE b/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/build.properties b/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 0a7bc7d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- plugin.xml,\
- icons/,\
- layoutlib_api.jar,\
- kxml2-2.3.0.jar,\
- ninepatch.jar,\
- layoutlib_utils.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
deleted file mode 100644
index 3779d4d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
+++ /dev/null
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
deleted file mode 100644
index 64e3601..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
+++ /dev/null
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
deleted file mode 100644
index 9cfb53f..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
+++ /dev/null
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png b/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
deleted file mode 100644
index afdc16c..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
+++ /dev/null
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
deleted file mode 100644
index 2678a5d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- point="org.eclipse.ui.editors">
- <editor
- class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
- default="true"
- filenames="AndroidManifest.xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
- name="Android Manifest Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
- name="Android Resource Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.layout.LayoutEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.layout.LayoutEditor"
- matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
- name="Android Layout Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.menu.MenuEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.menu.MenuEditor"
- name="Android Menu Editor">
- </editor>
- <editor
- class="com.android.ide.eclipse.editors.xml.XmlEditor"
- default="false"
- extensions="xml"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.xml.XmlEditor"
- name="Android Xml Resources Editor">
- </editor>
- </extension>
- <extension
- point="org.eclipse.wst.sse.ui.editorConfiguration">
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
- target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
- target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
- target="com.android.ide.eclipse.editors.layout.LayoutEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
- target="com.android.ide.eclipse.editors.menu.MenuEditor">
- </sourceViewerConfiguration>
- <sourceViewerConfiguration
- class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
- target="com.android.ide.eclipse.editors.xml.XmlEditor">
- </sourceViewerConfiguration>
- </extension>
- <extension
- point="org.eclipse.ui.views">
- <view
- allowMultiple="false"
- category="com.android.ide.eclipse.ddms.views.category"
- class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
- name="Resource Explorer">
- </view>
- </extension>
- <extension
- point="org.eclipse.ui.newWizards">
- <wizard
- canFinishEarly="false"
- category="com.android.ide.eclipse.wizards.category"
- class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
- finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
- hasPages="true"
- icon="icons/android.png"
- id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
- name="Android XML File"
- preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
- project="false">
- </wizard>
- </extension>
- <extension
- point="org.eclipse.ui.perspectiveExtensions">
- <perspectiveExtension
- targetID="org.eclipse.jdt.ui.JavaPerspective">
- <newWizardShortcut
- id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard">
- </newWizardShortcut>
- </perspectiveExtension>
- </extension>
-
-</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
deleted file mode 100644
index 354276a..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Copyright (C) 2007 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.editors;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-import com.android.ide.eclipse.common.SdkStatsHelper;
-import com.android.ide.eclipse.common.StreamHelper;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge.LoadStatus;
-import com.android.ide.eclipse.editors.layout.LayoutEditor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
-import com.android.ide.eclipse.editors.menu.MenuEditor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
-import com.android.ide.eclipse.editors.resources.ResourcesEditor;
-import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
-import com.android.ide.eclipse.editors.xml.XmlEditor;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
-import com.android.layoutlib.api.ILayoutBridge;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IEditorDescriptor;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.console.MessageConsoleStream;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.part.FileEditorInput;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class EditorsPlugin extends AbstractUIPlugin {
- // The shared instance
- private static EditorsPlugin sPlugin;
-
- private static Image sAndroidLogo;
- private static ImageDescriptor sAndroidLogoDesc;
-
- private ResourceMonitor mResourceMonitor;
- private SdkPathChangedListener mSdkPathChangedListener;
- private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
-
- private MessageConsoleStream mAndroidConsoleStream;
- /** Stream to write error messages to the android console */
- private MessageConsoleStream mAndroidConsoleErrorStream;
-
- public final static class LayoutBridge {
- public enum LoadStatus { LOADING, LOADED, FAILED }
-
- /** Link to the layout bridge */
- public ILayoutBridge bridge;
-
- public LoadStatus status = LoadStatus.LOADING;
- }
-
- private final LayoutBridge mLayoutBridge = new LayoutBridge();
-
- private boolean mLayoutBridgeInit;
-
- private ClassLoader mBridgeClassLoader;
-
- private Color mRed;
-
-
- /**
- * The constructor
- */
- public EditorsPlugin() {
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method refreshes the plug-in actions. Subclasses may extend this method,
- * but must send super <b>first</b>.
- * {@inheritDoc}
- *
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- sPlugin = this;
- sAndroidLogoDesc = imageDescriptorFromPlugin(AndroidConstants.EDITORS_PLUGIN_ID,
- "/icons/android.png"); //$NON-NLS-1$
- sAndroidLogo = sAndroidLogoDesc.createImage();
-
- // get the stream to write in the android console.
- MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
- mAndroidConsoleStream = androidConsole.newMessageStream();
-
- mAndroidConsoleErrorStream = androidConsole.newMessageStream();
- mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
-
- // because this can be run, in some cases, by a non ui thread, and beccause
- // changing the console properties update the ui, we need to make this change
- // in the ui thread.
- getDisplay().asyncExec(new Runnable() {
- public void run() {
- mAndroidConsoleErrorStream.setColor(mRed);
- }
- });
-
- // Add a resource listener to handle compiled resources.
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- mResourceMonitor = ResourceMonitor.startMonitoring(ws);
-
- if (mResourceMonitor != null) {
- setupDefaultEditor(mResourceMonitor);
- ResourceManager.setup(mResourceMonitor);
- }
-
- // Setup the sdk location changed listener and invoke it the first time
- mSdkPathChangedListener = new SdkPathChangedListener();
- FrameworkResourceManager.getInstance().addFrameworkResourcesChangeListener(
- mSdkPathChangedListener);
-
- // ping the usage server
- pingUsageServer();
- }
-
- /**
- * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
- * method saves this plug-in's preference and dialog stores and shuts down
- * its image registry (if they are in use). Subclasses may extend this
- * method, but must send super <b>last</b>. A try-finally statement should
- * be used where necessary to ensure that <code>super.shutdown()</code> is
- * always done.
- *
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- sAndroidLogo.dispose();
-
- IconFactory.getInstance().Dispose();
-
- // Remove the resource listener that handles compiled resources.
- IWorkspace ws = ResourcesPlugin.getWorkspace();
- ResourceMonitor.stopMonitoring(ws);
-
- FrameworkResourceManager.getInstance().removeFrameworkResourcesChangeListener(
- mSdkPathChangedListener);
- mSdkPathChangedListener = null;
-
- mRed.dispose();
-
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static EditorsPlugin getDefault() {
- return sPlugin;
- }
-
- /**
- * Returns an Image for the small Android logo.
- *
- * Callers should not dispose it.
- */
- public static Image getAndroidLogo() {
- return sAndroidLogo;
- }
-
- /**
- * Returns an {@link ImageDescriptor} for the small Android logo.
- *
- * Callers should not dispose it.
- */
- public static ImageDescriptor getAndroidLogoDesc() {
- return sAndroidLogoDesc;
- }
-
- /**
- * Logs a message to the default Eclipse log.
- *
- * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(int severity, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(severity, AndroidConstants.EDITORS_PLUGIN_ID, message);
- getDefault().getLog().log(status);
- }
-
- /**
- * Logs an exception to the default Eclipse log.
- * <p/>
- * The status severity is always set to ERROR.
- *
- * @param exception The exception to log. Its call trace will be recorded.
- * @param format The format string, like for String.format().
- * @param args The arguments for the format string, like for String.format().
- */
- public static void log(Throwable exception, String format, Object ... args) {
- String message = String.format(format, args);
- Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
- message, exception);
- getDefault().getLog().log(status);
- }
-
- /**
- * Returns the ResourceMonitor object.
- */
- public ResourceMonitor getResourceMonitor() {
- return mResourceMonitor;
- }
-
-
- /**
- * Sets up the editor to register default editors for resource files when needed.
- *
- * This is called by the {@link EditorsPlugin} during initialization.
- *
- * @param monitor The main Resource Monitor object.
- */
- public void setupDefaultEditor(ResourceMonitor monitor) {
- monitor.addFileListener(new IFileListener() {
-
- private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
-
- /* (non-Javadoc)
- * Sent when a file changed.
- * @param file The file that changed.
- * @param markerDeltas The marker deltas for the file.
- * @param kind The change kind. This is equivalent to
- * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
- *
- * @see IFileListener#fileChanged
- */
- public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
- if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
- // The resources files must have a file path similar to
- // project/res/.../*.xml
- // There is no support for sub folders, so the segment count must be 4
- if (file.getFullPath().segmentCount() == 4) {
- // check if we are inside the res folder.
- String segment = file.getFullPath().segment(1);
- if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
- // we are inside a res/ folder, get the actual ResourceFolder
- ProjectResources resources = ResourceManager.getInstance().
- getProjectResources(file.getProject());
-
- // This happens when importing old Android projects in Eclipse
- // that lack the container (probably because resources fail to build
- // properly.)
- if (resources == null) {
- log(IStatus.INFO,
- "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
- file.getFullPath().toOSString(),
- file.getProject().getName());
- return;
- }
-
- ResourceFolder resFolder = resources.getResourceFolder(
- (IFolder)file.getParent());
-
- if (resFolder != null) {
- if (kind == IResourceDelta.ADDED) {
- resourceAdded(file, resFolder.getType());
- } else if (kind == IResourceDelta.CHANGED) {
- resourceChanged(file, resFolder.getType());
- }
- } else {
- // if the res folder is null, this means the name is invalid,
- // in this case we remove whatever android editors that was set
- // as the default editor.
- IEditorDescriptor desc = IDE.getDefaultEditor(file);
- String editorId = desc.getId();
- if (editorId.startsWith(AndroidConstants.EDITORS_PLUGIN_ID)) {
- // reset the default editor.
- IDE.setDefaultEditor(file, null);
- }
- }
- }
- }
- }
- }
-
- private void resourceAdded(IFile file, ResourceFolderType type) {
- // set the default editor based on the type.
- if (type == ResourceFolderType.LAYOUT) {
- IDE.setDefaultEditor(file, LayoutEditor.ID);
- } else if (type == ResourceFolderType.DRAWABLE
- || type == ResourceFolderType.VALUES) {
- IDE.setDefaultEditor(file, ResourcesEditor.ID);
- } else if (type == ResourceFolderType.MENU) {
- IDE.setDefaultEditor(file, MenuEditor.ID);
- } else if (type == ResourceFolderType.XML) {
- if (XmlEditor.canHandleFile(file)) {
- IDE.setDefaultEditor(file, XmlEditor.ID);
- } else {
- // set a property to determine later if the XML can be handled
- QualifiedName qname = new QualifiedName(
- AndroidConstants.EDITORS_PLUGIN_ID,
- UNKNOWN_EDITOR);
- try {
- file.setPersistentProperty(qname, "1");
- } catch (CoreException e) {
- // pass
- }
- }
- }
- }
-
- private void resourceChanged(IFile file, ResourceFolderType type) {
- if (type == ResourceFolderType.XML) {
- IEditorDescriptor ed = IDE.getDefaultEditor(file);
- if (ed == null || ed.getId() != XmlEditor.ID) {
- QualifiedName qname = new QualifiedName(
- AndroidConstants.EDITORS_PLUGIN_ID,
- UNKNOWN_EDITOR);
- String prop = null;
- try {
- prop = file.getPersistentProperty(qname);
- } catch (CoreException e) {
- // pass
- }
- if (prop != null && XmlEditor.canHandleFile(file)) {
- try {
- // remove the property & set editor
- file.setPersistentProperty(qname, null);
- IWorkbenchPage page = PlatformUI.getWorkbench().
- getActiveWorkbenchWindow().getActivePage();
-
- IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
- if (oldEditor != null &&
- CommonPlugin.displayPrompt("Android XML Editor",
- String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
- file.getFullPath()))) {
- IDE.setDefaultEditor(file, XmlEditor.ID);
- IEditorPart newEditor = page.openEditor(
- new FileEditorInput(file),
- XmlEditor.ID,
- true, /* activate */
- IWorkbenchPage.MATCH_NONE);
-
- if (newEditor != null) {
- page.closeEditor(oldEditor, true /* save */);
- }
- }
- } catch (CoreException e) {
- // setPersistentProperty or page.openEditor may have failed
- }
- }
- }
- }
- }
-
- }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
- }
-
- /**
- * Respond to notifications from the resource manager than the SDK resources have been updated.
- * It gets the new resources from the {@link FrameworkResourceManager} and then try to update
- * the layout descriptors from the new layout data.
- */
- private class SdkPathChangedListener implements Runnable {
- public void run() {
-
- // Perform the update in a thread (here an Eclipse runtime job)
- // since this should never block the caller (especially the start method)
- new Job("Editors: Load Framework Resource Parser") {
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- SubMonitor progress = SubMonitor.convert(monitor, "Update Description",
- 60);
-
- FrameworkResourceManager resourceManager = FrameworkResourceManager.getInstance();
-
- AndroidManifestDescriptors.updateDescriptors(
- resourceManager.getManifestDefinitions());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- LayoutDescriptors.getInstance().updateDescriptors(
- resourceManager.getLayoutViewsInfo(),
- resourceManager.getLayoutGroupsInfo());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- MenuDescriptors.getInstance().updateDescriptors(
- resourceManager.getXmlMenuDefinitions());
- progress.worked(10);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
- XmlDescriptors.getInstance().updateDescriptors(
- resourceManager.getXmlSearchableDefinitions(),
- resourceManager.getPreferencesInfo(),
- resourceManager.getPreferenceGroupsInfo());
- progress.worked(10);
-
- // load the layout lib bridge.
- if (System.getenv("ANDROID_DISABLE_LAYOUT") == null) {
- loadLayoutBridge();
- FrameworkResourceManager frMgr = FrameworkResourceManager.getInstance();
- ResourceManager rMgr = ResourceManager.getInstance();
- rMgr.loadFrameworkResources(frMgr.getFrameworkResourcesLocation());
- }
- progress.worked(10);
-
- // Notify resource changed listeners
- progress.subTask("Refresh UI");
- progress.setWorkRemaining(mResourceRefreshListener.size());
-
- // Clone the list before iterating, to avoid Concurrent Modification
- // exceptions
- @SuppressWarnings("unchecked")
- ArrayList<Runnable> listeners = (ArrayList<Runnable>)
- mResourceRefreshListener.clone();
- for (Runnable listener : listeners) {
- try {
- getDisplay().syncExec(listener);
- } catch (Exception e) {
- log(e, "ResourceRefreshListener Failed"); //$NON-NLS-1$
- } finally {
- progress.worked(1);
- }
- }
- } catch (Throwable e) {
- EditorsPlugin.log(e, "Load Framework Resource Parser failed"); //$NON-NLS-1$
- EditorsPlugin.printToConsole("Framework Resource Parser",
- "Failed to parse");
- } finally {
- if (monitor != null) {
- monitor.done();
- }
- }
- return Status.OK_STATUS;
- }
- }.schedule();
- }
- }
-
- public void addResourceChangedListener(Runnable resourceRefreshListener) {
- mResourceRefreshListener.add(resourceRefreshListener);
- }
-
- public void removeResourceChangedListener(Runnable resourceRefreshListener) {
- mResourceRefreshListener.remove(resourceRefreshListener);
- }
-
- public static Display getDisplay() {
- IWorkbench bench = sPlugin.getWorkbench();
- if (bench != null) {
- return bench.getDisplay();
- }
- return null;
- }
-
- /**
- * Pings the usage start server.
- */
- private void pingUsageServer() {
- // In order to not block the plugin loading, so we spawn another thread.
- new Thread("Ping!") { //$NON-NLS-1$
- @Override
- public void run() {
- // get the version of the plugin
- String versionString = (String) getBundle().getHeaders().get(
- Constants.BUNDLE_VERSION);
- Version version = new Version(versionString);
-
- SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
- }
- }.start();
-
- }
-
- /**
- * Prints one or more message to the android console.
- * @param tag The tag to be associated with the message. Can be null.
- * @param objects the objects to print through their <code>toString</code> method.
- */
- public static synchronized void printToConsole(String tag, Object... objects) {
- StreamHelper.printToStream(sPlugin.mAndroidConsoleStream, tag, objects);
- }
-
- /**
- * Prints one or more error messages to the android console.
- * @param tag The tag to be associated with the message. Can be null.
- * @param objects the objects to print through their <code>toString</code> method.
- */
- public static synchronized void printErrorToConsole(String tag, Object... objects) {
- StreamHelper.printToStream(sPlugin.mAndroidConsoleErrorStream, tag, objects);
- }
-
- public static synchronized OutputStream getErrorStream() {
- return sPlugin.mAndroidConsoleErrorStream;
- }
-
- /**
- * Displays an error dialog box. This dialog box is ran asynchronously in the ui thread,
- * therefore this method can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- */
- public final static void displayError(final String title, final String message) {
- // get the current Display
- final Display display = getDisplay();
-
- // dialog box only run in ui thread..
- display.asyncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- MessageDialog.openError(shell, title, message);
- }
- });
- }
-
- /**
- * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
- * therefore this message can be called from any thread.
- * @param title The title of the dialog box
- * @param message The error message
- * @return true if OK was clicked.
- */
- public final static boolean displayPrompt(final String title, final String message) {
- // get the current Display and Shell
- final Display display = getDisplay();
-
- // we need to ask the user what he wants to do.
- final boolean[] wrapper = new boolean[] { false };
- display.syncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- wrapper[0] = MessageDialog.openQuestion(shell, title, message);
- }
- });
- return wrapper[0];
- }
-
- /**
- * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
- * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
- * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
- * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
- */
- public synchronized LayoutBridge getLayoutBridge() {
- if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
- FrameworkResourceManager manager = FrameworkResourceManager.getInstance();
- mLayoutBridge.bridge.init(
- manager.getFrameworkFontLocation() + AndroidConstants.FD_DEFAULT_RES,
- manager.getEnumValueMap());
- mLayoutBridgeInit = true;
- }
- return mLayoutBridge;
- }
-
- /**
- * Loads the layout bridge from the dynamically loaded layoutlib.jar
- */
- private void loadLayoutBridge() {
- try {
- // reset to be sure we won't be using an obsolete version if we
- // get an exception somewhere.
- mLayoutBridge.bridge = null;
- mLayoutBridge.status = LayoutBridge.LoadStatus.LOADING;
-
- // get the URL for the file.
- File f = new File(
- FrameworkResourceManager.getInstance().getLayoutLibLocation());
- if (f.isFile() == false) {
- log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
- } else {
- URL url = f.toURL();
-
- // create a class loader. Because this jar reference interfaces
- // that are in the editors plugin, it's important to provide
- // a parent class loader.
- mBridgeClassLoader = new URLClassLoader(new URL[] { url },
- this.getClass().getClassLoader());
-
- // load the class
- Class<?> clazz = mBridgeClassLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
- if (clazz != null) {
- // instantiate an object of the class.
- Constructor<?> constructor = clazz.getConstructor();
- if (constructor != null) {
- Object bridge = constructor.newInstance();
- if (bridge instanceof ILayoutBridge) {
- mLayoutBridge.bridge = (ILayoutBridge)bridge;
- }
- }
- }
-
- if (mLayoutBridge.bridge == null) {
- mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
- log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
- } else {
- mLayoutBridge.status = LayoutBridge.LoadStatus.LOADED;
- }
- }
- } catch (Throwable t) {
- mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
- // log the error.
- log(t, "Failed to load the LayoutLib");
- }
- }
-
- public ClassLoader getLayoutlibBridgeClassLoader() {
- return mBridgeClassLoader;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
deleted file mode 100644
index c936be3..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-import org.eclipse.ui.part.FileEditorInput;
-
-/**
- * Page for the layout tree-based form editor.
- *
- * @deprecated This is being phased out. We use the GraphicalLayoutEditor instead.
- */
-public final class LayoutTreePage extends FormPage {
- /** Page id used for switching tabs programmatically */
- public final static String PAGE_ID = "layout_tree_page"; //$NON-NLS-1$
-
- /** Container editor */
- LayoutEditor mEditor;
-
- public LayoutTreePage(LayoutEditor editor) {
- super(editor, PAGE_ID, "Layout"); // tab's label, keep it short
- mEditor = editor;
- }
-
- /**
- * Creates the content in the form hosted in this page.
- *
- * @param managedForm the form hosted in this page.
- */
- @Override
- protected void createFormContent(IManagedForm managedForm) {
- super.createFormContent(managedForm);
- ScrolledForm form = managedForm.getForm();
-
- String configText = null;
- IEditorInput input = mEditor.getEditorInput();
- if (input instanceof FileEditorInput) {
- FileEditorInput fileInput = (FileEditorInput)input;
- IFile iFile = fileInput.getFile();
-
- ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile);
- if (resFolder != null) {
- configText = resFolder.getConfiguration().toDisplayString();
- }
- }
-
- if (configText != null) {
- form.setText(String.format("Android Layout (%1$s)", configText));
- } else {
- form.setText("Android Layout");
- }
-
- form.setImage(EditorsPlugin.getAndroidLogo());
-
- UiElementNode rootNode = mEditor.getUiRootNode();
- UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
- true /* autoCreateRoot */,
- null /* no element filters */,
- "Layout Elements",
- "List of all layout elements in this XML file.");
- block.createContent(managedForm);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
deleted file mode 100644
index 77b1df4..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-
-import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
-import org.eclipse.gef.palette.MarqueeToolEntry;
-import org.eclipse.gef.palette.PaletteDrawer;
-import org.eclipse.gef.palette.PaletteGroup;
-import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.palette.PanningSelectionToolEntry;
-import org.eclipse.gef.requests.CreationFactory;
-
-import java.util.List;
-
-/**
- * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
- */
-public class PaletteFactory {
-
- private static PaletteRoot sPaletteRoot;
- private static Runnable sSdkChangedListener;
-
- /** Static factory, nothing to instantiate here. */
- private PaletteFactory() {
- }
-
- public static PaletteRoot createPaletteRoot() {
- if (sSdkChangedListener == null) {
- sSdkChangedListener = new Runnable() {
- public void run() {
- if (sPaletteRoot != null) {
- // The SDK has changed. Remove the drawer groups and rebuild them.
- for (int n = sPaletteRoot.getChildren().size() - 1; n >= 0; n--) {
- sPaletteRoot.getChildren().remove(n);
- }
-
- addTools(sPaletteRoot);
- addViews(sPaletteRoot, "Layouts",
- LayoutDescriptors.getInstance().getLayoutDescriptors());
- addViews(sPaletteRoot, "Views",
- LayoutDescriptors.getInstance().getViewDescriptors());
- }
- }
- };
- EditorsPlugin.getDefault().addResourceChangedListener(sSdkChangedListener);
- }
-
- if (sPaletteRoot == null) {
- sPaletteRoot = new PaletteRoot();
- sSdkChangedListener.run();
- }
- return sPaletteRoot;
- }
-
- private static void addTools(PaletteRoot paletteRoot) {
- PaletteGroup group = new PaletteGroup("Tools");
-
- // Default tools: selection and marquee selection
- PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
- group.add(entry);
- paletteRoot.setDefaultEntry(entry);
-
- group.add(new MarqueeToolEntry());
-
- paletteRoot.add(group);
- }
-
- private static void addViews(PaletteRoot paletteRoot, String groupName,
- List<ElementDescriptor> descriptors) {
- PaletteDrawer group = new PaletteDrawer(groupName);
-
- for (ElementDescriptor desc : descriptors) {
- CombinedTemplateCreationEntry entry = new CombinedTemplateCreationEntry(
- desc.getUiName(), // label
- desc.getTooltip(), // short description
- desc.getClass(), // template
- new ElementFactory(desc), // factory
- desc.getImageDescriptor(), // small icon
- desc.getImageDescriptor() // large icon
- );
- group.add(entry);
- }
-
- paletteRoot.add(group);
- }
-
- //------------------------------------------
-
- public static class ElementFactory implements CreationFactory {
-
- private final ElementDescriptor mDescriptor;
-
- public ElementFactory(ElementDescriptor descriptor) {
- mDescriptor = descriptor;
- }
-
- public Object getNewObject() {
- return mDescriptor;
- }
-
- public Object getObjectType() {
- return mDescriptor;
- }
-
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
deleted file mode 100644
index 41d3747..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import com.android.layoutlib.api.IXmlPullParser;
-
-import org.w3c.dom.Node;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * XmlPullParser implementation on top of {@link UiElementNode}.
- * <p/>It's designed to work on layout files, and will most likely not work on other resource
- * files.
- */
-public final class UiElementPullParser implements IXmlPullParser {
-
- private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
- private int mParsingState = START_DOCUMENT;
- private UiElementNode mRoot;
-
- public UiElementPullParser(UiElementNode top) {
- mRoot = top;
- push(mRoot);
- }
-
- private UiElementNode getCurrentNode() {
- if (mNodeStack.size() > 0) {
- return mNodeStack.get(mNodeStack.size()-1);
- }
-
- return null;
- }
-
- private Node getAttribute(int i) {
- if (mParsingState != START_TAG) {
- throw new IndexOutOfBoundsException();
- }
-
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- return xmlNode.getAttributes().item(i);
- }
-
- return null;
- }
-
- private void push(UiElementNode node) {
- mNodeStack.add(node);
- }
-
- private UiElementNode pop() {
- return mNodeStack.remove(mNodeStack.size()-1);
- }
-
- // ------------- IXmlPullParser --------
-
- /**
- * {@inheritDoc}
- *
- * This implementation returns the underlying DOM node.
- */
- public Object getViewKey() {
- return getCurrentNode();
- }
-
- // ------------- XmlPullParser --------
-
- public void setFeature(String name, boolean state) throws XmlPullParserException {
- if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
- return;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
- return;
- }
- throw new XmlPullParserException("Unsupported feature: " + name);
- }
-
- public boolean getFeature(String name) {
- if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
- return true;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
- return true;
- }
- return false;
- }
-
- public void setProperty(String name, Object value) throws XmlPullParserException {
- throw new XmlPullParserException("setProperty() not supported");
- }
-
- public Object getProperty(String name) {
- return null;
- }
-
- public void setInput(Reader in) throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
-
- public void setInput(InputStream inputStream, String inputEncoding)
- throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
-
- public void defineEntityReplacementText(String entityName, String replacementText)
- throws XmlPullParserException {
- throw new XmlPullParserException("defineEntityReplacementText() not supported");
- }
-
- public String getNamespacePrefix(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespacePrefix() not supported");
- }
-
- public String getInputEncoding() {
- return null;
- }
-
- public String getNamespace(String prefix) {
- throw new RuntimeException("getNamespace() not supported");
- }
-
- public int getNamespaceCount(int depth) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceCount() not supported");
- }
-
- public String getPositionDescription() {
- return "XML DOM element depth:" + mNodeStack.size();
- }
-
- public String getNamespaceUri(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceUri() not supported");
- }
-
- public int getColumnNumber() {
- return -1;
- }
-
- public int getLineNumber() {
- return -1;
- }
-
- public int getAttributeCount() {
- UiElementNode node = getCurrentNode();
- if (node != null) {
- return node.getUiAttributes().size();
- }
-
- return 0;
- }
-
- public String getAttributeName(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getLocalName();
- }
-
- return null;
- }
-
- public String getAttributeNamespace(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getNamespaceURI();
- }
- return ""; //$NON-NLS-1$
- }
-
- public String getAttributePrefix(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getPrefix();
- }
- return null;
- }
-
- public String getAttributeType(int arg0) {
- return "CDATA";
- }
-
- public String getAttributeValue(int i) {
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getNodeValue();
- }
-
- return null;
- }
-
- public String getAttributeValue(String namespace, String localName) {
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
- if (attribute != null) {
- return attribute.getNodeValue();
- }
- }
-
- return null;
- }
-
- public int getDepth() {
- return mNodeStack.size();
- }
-
- public int getEventType() throws XmlPullParserException {
- return mParsingState;
- }
-
- public String getName() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- return getCurrentNode().getDescriptor().getXmlLocalName();
- }
-
- return null;
- }
-
- public String getNamespace() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- return getCurrentNode().getDescriptor().getNamespace();
- }
-
- return null;
- }
-
- public String getPrefix() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- // FIXME will NEVER work
- if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
- return "android"; //$NON-NLS-1$
- }
- }
-
- return null;
- }
-
- public String getText() {
- return null;
- }
-
- public char[] getTextCharacters(int[] arg0) {
- return null;
- }
-
- public boolean isAttributeDefault(int arg0) {
- return false;
- }
-
- public boolean isEmptyElementTag() throws XmlPullParserException {
- if (mParsingState == START_TAG) {
- return getCurrentNode().getUiChildren().size() == 0;
- }
-
- throw new XmlPullParserException("Must be on START_TAG");
- }
-
- public boolean isWhitespace() throws XmlPullParserException {
- return false;
- }
-
- public int next() throws XmlPullParserException, IOException {
- UiElementNode node;
- switch (mParsingState) {
- case END_DOCUMENT:
- throw new XmlPullParserException("Nothing after the end");
- case START_DOCUMENT:
- /* intended fall-through */
- case START_TAG:
- // get the current node, and look for text or children (children first)
- node = getCurrentNode();
- List<UiElementNode> children = node.getUiChildren();
- if (children.size() > 0) {
- // move to the new child, and don't change the state.
- push(children.get(0));
-
- // in case the current state is CURRENT_DOC, we set the proper state.
- mParsingState = START_TAG;
- } else {
- if (mParsingState == START_DOCUMENT) {
- // this handles the case where there's no node.
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- break;
- case END_TAG:
- // look for a sibling. if no sibling, go back to the parent
- node = getCurrentNode();
- node = node.getUiNextSibling();
- if (node != null) {
- // to go to the sibling, we need to remove the current node,
- pop();
- // and add its sibling.
- push(node);
- mParsingState = START_TAG;
- } else {
- // move back to the parent
- pop();
-
- // we have only one element left (mRoot), then we're done with the document.
- if (mNodeStack.size() == 1) {
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- break;
- case TEXT:
- // not used
- break;
- case CDSECT:
- // not used
- break;
- case ENTITY_REF:
- // not used
- break;
- case IGNORABLE_WHITESPACE:
- // not used
- break;
- case PROCESSING_INSTRUCTION:
- // not used
- break;
- case COMMENT:
- // not used
- break;
- case DOCDECL:
- // not used
- break;
- }
-
- return mParsingState;
- }
-
- public int nextTag() throws XmlPullParserException, IOException {
- int eventType = next();
- if (eventType != START_TAG && eventType != END_TAG) {
- throw new XmlPullParserException("expected start or end tag", this, null);
- }
- return eventType;
- }
-
- public String nextText() throws XmlPullParserException, IOException {
- if (getEventType() != START_TAG) {
- throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
- null);
- }
- int eventType = next();
- if (eventType == TEXT) {
- String result = getText();
- eventType = next();
- if (eventType != END_TAG) {
- throw new XmlPullParserException(
- "event TEXT it must be immediately followed by END_TAG", this, null);
- }
- return result;
- } else if (eventType == END_TAG) {
- return "";
- } else {
- throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
- this, null);
- }
- }
-
- public int nextToken() throws XmlPullParserException, IOException {
- return next();
- }
-
- public void require(int type, String namespace, String name) throws XmlPullParserException,
- IOException {
- if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
- || (name != null && !name.equals(getName())))
- throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
deleted file mode 100644
index 548a3a2..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout.parts;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.draw2d.geometry.Rectangle;
-import org.eclipse.gef.DragTracker;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gef.GraphicalEditPart;
-import org.eclipse.gef.Request;
-import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
-import org.eclipse.gef.editpolicies.SelectionEditPolicy;
-import org.eclipse.gef.tools.SelectEditPartTracker;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import java.util.List;
-
-/**
- * An {@link EditPart} for a {@link UiElementNode}.
- */
-public abstract class UiElementEditPart extends AbstractGraphicalEditPart
- implements IUiUpdateListener {
-
- public UiElementEditPart(UiElementNode uiElementNode) {
- setModel(uiElementNode);
- }
-
- //-------------------------
- // Derived classes must define these
-
- abstract protected void hideSelection();
- abstract protected void showSelection();
-
- //-------------------------
- // Base class overrides
-
- @Override
- public DragTracker getDragTracker(Request request) {
- return new SelectEditPartTracker(this);
- }
-
- @Override
- protected void createEditPolicies() {
- installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new SelectionEditPolicy() {
- @Override
- protected void hideSelection() {
- UiElementEditPart.this.hideSelection();
- }
-
- @Override
- protected void showSelection() {
- UiElementEditPart.this.showSelection();
- }
- });
- // TODO add editing policies
- }
-
- /* (non-javadoc)
- * Returns a List containing the children model objects.
- * Must not return null, instead use the super which returns an empty list.
- */
- @SuppressWarnings("unchecked")
- @Override
- protected List getModelChildren() {
- return getUiNode().getUiChildren();
- }
-
- @Override
- public void activate() {
- super.activate();
- getUiNode().addUpdateListener(this);
- }
-
- @Override
- public void deactivate() {
- super.deactivate();
- getUiNode().removeUpdateListener(this);
- }
-
- @Override
- protected void refreshVisuals() {
- if (getFigure().getParent() != null) {
- ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
- }
-
- // update the visuals of the children as well
- refreshChildrenVisuals();
- }
-
- protected void refreshChildrenVisuals() {
- if (children != null) {
- for (Object child : children) {
- if (child instanceof UiElementEditPart) {
- UiElementEditPart childPart = (UiElementEditPart)child;
- childPart.refreshVisuals();
- }
- }
- }
- }
-
- //-------------------------
- // IUiUpdateListener implementation
-
- public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
- // TODO: optimize by refreshing only when needed
- switch(state) {
- case ATTR_UPDATED:
- refreshVisuals();
- break;
- case CHILDREN_CHANGED:
- refreshChildren();
-
- // new children list, need to update the layout
- refreshVisuals();
- break;
- case CREATED:
- refreshVisuals();
- break;
- case DELETED:
- // pass
- break;
- }
- }
-
- //-------------------------
- // Local methods
-
- /** @return The object model casted to an {@link UiElementNode} */
- protected final UiElementNode getUiNode() {
- return (UiElementNode) getModel();
- }
-
- protected final ElementDescriptor getDescriptor() {
- return getUiNode().getDescriptor();
- }
-
- protected final UiElementEditPart getEditPartParent() {
- EditPart parent = getParent();
- if (parent instanceof UiElementEditPart) {
- return (UiElementEditPart)parent;
- }
- return null;
- }
-
- /**
- * Returns a given XML attribute.
- * @param attrbName The local name of the attribute.
- * @return the attribute as a {@link String}, if it exists, or <code>null</code>
- */
- protected final String getStringAttr(String attrName) {
- UiElementNode uiNode = getUiNode();
- if (uiNode.getXmlNode() != null) {
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode != null) {
- NamedNodeMap nodeAttributes = xmlNode.getAttributes();
- if (nodeAttributes != null) {
- Node attr = nodeAttributes.getNamedItemNS(
- AndroidConstants.NS_RESOURCES, attrName);
- if (attr != null) {
- return attr.getNodeValue();
- }
- }
- }
- }
- return null;
- }
-
- protected final Rectangle getBounds() {
- UiElementNode model = (UiElementNode)getModel();
-
- Object editData = model.getEditData();
- if (editData instanceof Rectangle) {
- return (Rectangle)editData; // return a copy?
- }
-
- // return a dummy rect
- return new Rectangle(0, 0, 0, 0);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
deleted file mode 100644
index 7e38032..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.apache.xml.serialize.Method;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.XMLSerializer;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.document.NodeContainer;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import java.io.StringWriter;
-
-
-/**
- * Provides Cut and Copy actions for the tree nodes.
- */
-public class CopyCutAction extends Action {
- private UiElementNode mUiNode;
- private boolean mPerformCut;
- private final AndroidEditor mEditor;
- private final Clipboard mClipboard;
- private final ICommitXml mXmlCommit;
-
- /**
- * Creates a new Copy or Cut action.
- *
- * @param ui_node The UI node to cut or copy. It *must* have a non-null XML node.
- * @param perform_cut True if the operation is cut, false if it is copy.
- */
- public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
- UiElementNode ui_node, boolean perform_cut) {
- super(perform_cut ? "Cut" : "Copy");
- mEditor = editor;
- mClipboard = clipboard;
- mXmlCommit = xmlCommit;
-
- ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
- if (perform_cut) {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
- } else {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
- }
-
- mUiNode = ui_node;
- mPerformCut = perform_cut;
- }
-
- /**
- * Performs the cut or copy action.
- * First an XML serializer is used to turn the existing XML node into a valid
- * XML fragment, which is added as text to the clipboard.
- */
- @Override
- public void run() {
- super.run();
- try {
- String data = null;
-
- // Get the data directly from the editor.
-
- // Commit the current pages first, to make sure the XML is in sync.
- if (mXmlCommit != null) {
- mXmlCommit.commitPendingXmlChanges();
- }
-
- // Committing may change the XML structure.
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node == null) {
- return;
- }
-
- IStructuredModel model = mEditor.getModelForRead();
- try {
- IStructuredDocument sse_doc = mEditor.getStructuredDocument();
- if (xml_node instanceof NodeContainer) {
- // The easy way to get the source of an SSE XML node.
- data = ((NodeContainer) xml_node).getSource();
- } else if (xml_node instanceof IndexedRegion && sse_doc != null) {
- // Try harder.
- IndexedRegion region = (IndexedRegion) xml_node;
- int start = region.getStartOffset();
- int end = region.getEndOffset();
-
- if (end > start) {
- data = sse_doc.get(start, end - start);
- }
- }
- } catch (BadLocationException e) {
- // the region offset was invalid. ignore.
- } finally {
- model.releaseFromRead();
- }
-
- // In the unlikely event that IStructuredDocument failed to extract the text
- // directly from the editor, try to fall back on a direct XML serialization
- // of the XML node. This uses the generic Node interface with no SSE tricks.
- if (data == null) {
- StringWriter sw = new StringWriter();
- XMLSerializer serializer = new XMLSerializer(sw,
- new OutputFormat(Method.XML,
- OutputFormat.Defaults.Encoding /* utf-8 */,
- true /* indent */));
- // Serialize will throw an IOException if it fails.
- serializer.serialize((Element) xml_node);
- data = sw.toString();
- }
-
- if (data != null && data.length() > 0) {
- mClipboard.setContents(
- new Object[] { data },
- new Transfer[] { TextTransfer.getInstance() });
- if (mPerformCut) {
- mUiNode.deleteXmlNode();
- }
- }
- } catch (Exception e) {
- EditorsPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
- mUiNode.getBreadcrumbTrailDescription(true));
- }
- }
-}
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
deleted file mode 100644
index b3d0755..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 com.android.ide.eclipse.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.swt.widgets.Shell;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-/**
- * Performs basic actions on an XML tree: add node, remove node, move up/down.
- */
-public abstract class UiActions implements ICommitXml {
-
- public UiActions() {
- }
-
- //---------------------
- // Actual implementations must override these to provide specific hooks
-
- /** Returns the UiDocumentNode for the current model. */
- abstract protected UiElementNode getRootNode();
-
- /** Commits pending data before the XML model is modified. */
- abstract public void commitPendingXmlChanges();
-
- /**
- * Utility method to select an outline item based on its model node
- *
- * @param ui_node The node to select. Can be null (in which case nothing should happen)
- */
- abstract protected void selectUiNode(UiElementNode ui_node);
-
- //---------------------
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- * <p/>
- * This simplified version of doAdd does not support descriptor filters and creates
- * a new {@link UiModelTreeLabelProvider} for each call.
- */
- public void doAdd(UiElementNode ui_node, Shell shell) {
- doAdd(ui_node, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
- }
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- *
- * Displays a selection dialog that lets the user select which kind of node
- * to create, depending on the current selection.
- */
- public void doAdd(UiElementNode ui_node,
- ElementDescriptor[] descriptorFilters,
- Shell shell, ILabelProvider labelProvider) {
- // If the root node is a document with already a root, use it as the root node
- UiElementNode root_node = getRootNode();
- if (root_node instanceof UiDocumentNode &&
- root_node.getUiChildren().size() > 0) {
- root_node = root_node.getUiChildren().get(0);
- }
-
- NewItemSelectionDialog dlg = new NewItemSelectionDialog(
- shell,
- labelProvider,
- descriptorFilters,
- ui_node, root_node);
- dlg.open();
- Object[] results = dlg.getResult();
- if (results != null && results.length > 0) {
- UiElementNode ui_new = addNewTreeElement(dlg.getChosenRootNode(),
- (ElementDescriptor) results[0]);
-
- selectUiNode(ui_new);
- }
- }
-
- /**
- * Called when the "Remove" button is selected.
- *
- * If the tree has a selection, remove it.
- * This simply deletes the XML node attached to the UI node: when the XML model fires the
- * update event, the tree will get refreshed.
- */
- public void doRemove(final UiElementNode ui_node, Shell shell) {
- if (MessageDialog.openQuestion(shell,
- "Remove element from Android XML", // title
- String.format("Do you really want to remove %1$s?",
- ui_node.getBreadcrumbTrailDescription(false /* include_root */)))) {
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- UiElementNode previous = ui_node.getUiPreviousSibling();
- UiElementNode parent = ui_node.getUiParent();
-
- // delete node
- ui_node.deleteXmlNode();
-
- // try to select the previous sibling or the parent
- if (previous != null) {
- selectUiNode(previous);
- } else if (parent != null) {
- selectUiNode(parent);
- }
- }
- });
- }
- }
-
- /**
- * Called when the "Up" button is selected.
- * <p/>
- * If the tree has a selection, move it up, either in the child list or as the last child
- * of the previous parent.
- */
- public void doUp(final UiElementNode ui_node) {
- final Node[] select_xml_node = { null };
- // the node will move either up to its parent or grand-parent
- UiElementNode search_root = ui_node.getUiParent();
- if (search_root != null && search_root.getUiParent() != null) {
- search_root = search_root.getUiParent();
- }
-
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- Node xml_node = ui_node.getXmlNode();
- if (xml_node != null) {
- Node xml_parent = xml_node.getParentNode();
- if (xml_parent != null) {
- UiElementNode ui_prev = ui_node.getUiPreviousSibling();
- if (ui_prev != null && ui_prev.getXmlNode() != null) {
- // This node is not the first one of the parent, so it can be
- // removed and then inserted before its previous sibling.
- // If the previous sibling can have children, though, then it
- // is inserted at the end of the children list.
- Node xml_prev = ui_prev.getXmlNode();
- if (ui_prev.getDescriptor().hasChildren()) {
- xml_prev.appendChild(xml_parent.removeChild(xml_node));
- select_xml_node[0] = xml_node;
- } else {
- xml_parent.insertBefore(
- xml_parent.removeChild(xml_node),
- xml_prev);
- select_xml_node[0] = xml_node;
- }
- } else if (!(xml_parent instanceof Document) &&
- xml_parent.getParentNode() != null &&
- !(xml_parent.getParentNode() instanceof Document)) {
- // If the node is the first one of the child list of its
- // parent, move it up in the hierarchy as previous sibling
- // to the parent. This is only possible if the parent of the
- // parent is not a document.
- Node grand_parent = xml_parent.getParentNode();
- grand_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_parent);
- select_xml_node[0] = xml_node;
- }
- }
- }
- }
- });
-
- if (select_xml_node[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(ui_node);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (search_root == null) {
- search_root = ui_node.getUiRoot();
- }
- if (search_root != null) {
- selectUiNode(search_root.findXmlNode(select_xml_node[0]));
- }
- }
- }
-
- /**
- * Called when the "Down" button is selected.
- *
- * If the tree has a selection, move it down, either in the same child list or as the
- * first child of the next parent.
- */
- public void doDown(final UiElementNode ui_node) {
- final Node[] select_xml_node = { null };
- // the node will move either down to its parent or grand-parent
- UiElementNode search_root = ui_node.getUiParent();
- if (search_root != null && search_root.getUiParent() != null) {
- search_root = search_root.getUiParent();
- }
-
- commitPendingXmlChanges();
- getRootNode().getEditor().editXmlModel(new Runnable() {
- public void run() {
- Node xml_node = ui_node.getXmlNode();
- if (xml_node != null) {
- Node xml_parent = xml_node.getParentNode();
- if (xml_parent != null) {
- UiElementNode ui_next = ui_node.getUiNextSibling();
- if (ui_next != null && ui_next.getXmlNode() != null) {
- // This node is not the last one of the parent, so it can be
- // removed and then inserted after its next sibling.
- // If the next sibling is a node that can have children, though,
- // then the node is inserted as the first child.
- Node xml_next = ui_next.getXmlNode();
- if (ui_next.getDescriptor().hasChildren()) {
- // Note: insertBefore works as append if the ref node is
- // null, i.e. when the node doesn't have children yet.
- xml_next.insertBefore(xml_parent.removeChild(xml_node),
- xml_next.getFirstChild());
- select_xml_node[0] = xml_node;
- } else {
- // Insert "before after next" ;-)
- xml_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_next.getNextSibling());
- select_xml_node[0] = xml_node;
- }
- } else if (!(xml_parent instanceof Document) &&
- xml_parent.getParentNode() != null &&
- !(xml_parent.getParentNode() instanceof Document)) {
- // This node is the last node of its parent.
- // If neither the parent nor the grandparent is a document,
- // then the node can be insert right after the parent.
- Node grand_parent = xml_parent.getParentNode();
- grand_parent.insertBefore(xml_parent.removeChild(xml_node),
- xml_parent.getNextSibling());
- select_xml_node[0] = xml_node;
- }
- }
- }
- }
- });
-
- if (select_xml_node[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(ui_node);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (search_root == null) {
- search_root = ui_node.getUiRoot();
- }
- if (search_root != null) {
- selectUiNode(search_root.findXmlNode(select_xml_node[0]));
- }
- }
- }
-
- //---------------------
-
- /**
- * Adds a new element of the given descriptor's type to the given UI parent node.
- *
- * This actually creates the corresponding XML node in the XML model, which in turn
- * will refresh the current tree view.
- *
- * @param ui_parent An existing UI node or null to add to the tree root
- * @param elementDescriptor The descriptor of the element to add
- * @return The {@link UiElementNode} that has been added to the UI tree.
- */
- private UiElementNode addNewTreeElement(UiElementNode ui_parent,
- ElementDescriptor elementDescriptor) {
- commitPendingXmlChanges();
- final UiElementNode ui_new = ui_parent.appendNewUiChild(elementDescriptor);
- UiElementNode root_node = getRootNode();
-
- root_node.getEditor().editXmlModel(new Runnable() {
- public void run() {
- DescriptorsUtils.setDefaultLayoutAttributes(ui_new);
- ui_new.createXmlNode();
- }
- });
- return ui_new;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/.classpath b/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
deleted file mode 100644
index 751c8f2..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/.project b/eclipse/plugins/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 145d97c..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>platform</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
deleted file mode 100644
index 178275a..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,15 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Platform Development Toolkit
-Bundle-SymbolicName: com.android.ide.eclipse.platform;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .
-Bundle-Activator: com.android.ide.eclipse.platform.AndroidPlatformPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime,
- com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.common,
- org.eclipse.core.resources,
- org.eclipse.jdt.core
-Eclipse-LazyStart: true
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL b/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE b/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
-
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/build.properties b/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 6c480f3..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .,\
- plugin.xml,\
- icons/
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png b/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
deleted file mode 100644
index 6171025..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
+++ /dev/null
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
deleted file mode 100644
index 1c5d067..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
- <extension
- id="PlatformNature"
- name="PlatformNature"
- point="org.eclipse.core.resources.natures">
- <runtime>
- <run class="com.android.ide.eclipse.platform.project.PlatformNature"/>
- </runtime>
- </extension>
- <extension
- point="org.eclipse.ui.ide.projectNatureImages">
- <image
- icon="icons/android_project.png"
- id="com.android.ide.eclipse.platform.PlatformNature.image"
- natureId="com.android.ide.eclipse.platform.PlatformNature">
- </image>
- </extension>
- <extension
- point="org.eclipse.ui.preferencePages">
- <page
- class="com.android.ide.eclipse.platform.preferences.AndroidPreferencePage"
- id="com.android.ide.eclipse.preferences.main"
- name="Android"/>
- </extension>
- <extension
- point="org.eclipse.jdt.core.classpathContainerInitializer">
- <classpathContainerInitializer
- class="com.android.ide.eclipse.platform.project.PlatformClasspathContainerInitializer"
- id="com.android.ide.eclipse.platform.DUMMY_CONTAINER">
- </classpathContainerInitializer>
- </extension>
- <extension
- point="org.eclipse.ui.popupMenus">
- <objectContribution
- id="com.android.ide.eclipse.platform.contribution1"
- nameFilter="*"
- objectClass="org.eclipse.core.resources.IProject"
- adaptable="true">
- <menu
- id="com.android.ide.eclipse.platform.AndroidTools"
- label="Android Tools"
- path="additions">
- <separator name="group1"/>
- </menu>
- <visibility>
- <not>
- <or>
- <objectState
- name="projectNature"
- value="com.android.ide.eclipse.platform.PlatformNature"/>
- <objectState
- name="open"
- value="false"/>
- </or>
- </not>
- </visibility>
- <action
- class="com.android.ide.eclipse.platform.project.ConvertToPlatformAction"
- enablesFor="1"
- id="com.android.ide.eclipse.platform.ConvertToPlatformAction"
- label="Convert To Android Project"
- menubarPath="com.android.ide.eclipse.platform.AndroidTools/group1"/>
- </objectContribution>
- </extension>
-</plugin>
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java b/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
deleted file mode 100644
index 5fa8a29..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 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.platform;
-
-import com.android.ddmuilib.StackTracePanel;
-import com.android.ddmuilib.StackTracePanel.ISourceRevealer;
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.project.BaseProjectHelper;
-import com.android.ide.eclipse.ddms.DdmsPlugin;
-import com.android.ide.eclipse.platform.project.PlatformNature;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.Preferences;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-import java.io.File;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class AndroidPlatformPlugin extends AbstractUIPlugin {
-
- // The plug-in ID
- public static final String PLUGIN_ID = "com.android.ide.eclipse.apdt"; //$NON-NLS-1$
-
- public final static String PREFS_DEVICE_DIRECTORY = PLUGIN_ID + ".deviceDir"; //$NON-NLS-1$
-
- // The shared instance
- private static AndroidPlatformPlugin sPlugin;
-
- private IPreferenceStore mStore;
- private String mOsDeviceDirectory;
-
- /**
- * The constructor
- */
- public AndroidPlatformPlugin() {
- sPlugin = this;
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
-
- // get the eclipse store
- mStore = getPreferenceStore();
-
- // set the listener for the preference change
- Preferences prefs = getPluginPreferences();
- prefs.addPropertyChangeListener(new IPropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent event) {
- // get the name of the property that changed.
- String property = event.getProperty();
-
- // if the SDK changed, we update the cached version
- if (PREFS_DEVICE_DIRECTORY.equals(property)) {
- // get the new one from the preferences
- mOsDeviceDirectory = (String)event.getNewValue();
-
- // make sure it does not ends with a separator
- if (mOsDeviceDirectory.endsWith(File.separator)) {
- mOsDeviceDirectory = mOsDeviceDirectory.substring(0,
- mOsDeviceDirectory.length() - 1);
- }
-
- // finally restart adb, in case it's a different version
- String adbLocation = getOsAdbLocation();
- if (adbLocation != null) {
- DdmsPlugin.setAdb(adbLocation, true /* startAdb */);
- }
- }
- }
- });
-
-
- mOsDeviceDirectory = mStore.getString(PREFS_DEVICE_DIRECTORY);
-
- if (mOsDeviceDirectory.length() == 0) {
- // get the current Display
- final Display display = sPlugin.getWorkbench().getDisplay();
-
- // dialog box only run in ui thread..
- display.asyncExec(new Runnable() {
- public void run() {
- Shell shell = display.getActiveShell();
- MessageDialog.openError(shell, "Android Preferences",
- "Location of the device directory is missing.");
- }
- });
- } else {
- // give the location of adb to ddms
- String adbLocation = getOsAdbLocation();
- if (adbLocation != null) {
- DdmsPlugin.setAdb(adbLocation, true);
- }
- }
-
- // and give it the debug launcher for android projects
- DdmsPlugin.setRunningAppDebugLauncher(new DdmsPlugin.IDebugLauncher() {
- public boolean debug(String packageName, int port) {
- return false;
- }
- });
-
- StackTracePanel.setSourceRevealer(new ISourceRevealer() {
- public void reveal(String applicationName, String className, int line) {
- IProject project = getDeviceProject();
- if (project != null) {
- BaseProjectHelper.revealSource(project, className, line);
- }
- }
- });
-
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- sPlugin = null;
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static AndroidPlatformPlugin getDefault() {
- return sPlugin;
- }
-
- /**
- * Returns the Android project. This is the first project which has the PlatformNature.
- * @return the <code>IProject</code> of the Android project, or <code>null</code> if it was
- * not found.
- */
- public static IProject getDeviceProject() {
- // Get the list of projects for the current workspace.
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- IProject[] projects = workspace.getRoot().getProjects();
-
- for (IProject project : projects) {
- try {
- if (project.hasNature(PlatformNature.ID)) {
- return project;
- }
- } catch (CoreException e) {
- // Failed to get the nature for this project. Let's just ignore
- // it and move on to the next one.
- }
- }
-
- return null;
- }
-
- /**
- * Returns the OS path of the adb location.
- * @return the location of adb or null if it cannot be computed.
- */
- private String getOsAdbLocation() {
- if (mOsDeviceDirectory == null || mOsDeviceDirectory.length() == 0) {
- return null;
- }
-
- if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_LINUX) {
- return mOsDeviceDirectory + "/out/host/linux-x86/bin/adb"; //$NON-NLS-1$
- } else if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_DARWIN) {
- return mOsDeviceDirectory + "/out/host/darwin-x86/bin/adb"; //$NON-NLS-1$
- }
- return null;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
deleted file mode 100644
index 8427bad..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 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.platform.preferences;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.jface.preference.DirectoryFieldEditor;
-import org.eclipse.jface.preference.FieldEditorPreferencePage;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPreferencePage;
-
-/**
- * This class represents a preference page that is contributed to the
- * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>,
- * we can use the field support built into JFace that allows us to create a page
- * that is small and knows how to save, restore and apply itself.
- * <p>
- * This page is used to modify preferences only. They are stored in the
- * preference store that belongs to the main plug-in class. That way,
- * preferences can be accessed directly via the preference store.
- */
-public class AndroidPreferencePage extends FieldEditorPreferencePage implements
- IWorkbenchPreferencePage {
-
- public AndroidPreferencePage() {
- super(GRID);
- setPreferenceStore(AndroidPlatformPlugin.getDefault().getPreferenceStore());
- setDescription("Android Preferences");
- }
-
- /**
- * Creates the field editors. Field editors are abstractions of the common
- * GUI blocks needed to manipulate various types of preferences. Each field
- * editor knows how to save and restore itself.
- */
- @Override
- public void createFieldEditors() {
- addField(new DirectoryFieldEditor(AndroidPlatformPlugin.PREFS_DEVICE_DIRECTORY,
- "Location of //device", getFieldEditorParent()));
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
- */
- public void init(IWorkbench workbench) {
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java b/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
deleted file mode 100644
index 58d55e5..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import java.util.Iterator;
-
-/**
- * Converts a project created with the activity creator into an
- * Android project.
- */
-public class ConvertToPlatformAction implements IObjectActionDelegate {
-
- private ISelection mSelection;
-
- /*
- * (non-Javadoc)
- *
- * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
- */
- public void setActivePart(IAction action, IWorkbenchPart targetPart) {
- // pass
- }
-
- /*
- * (non-Javadoc)
- *
- * @see IActionDelegate#run(IAction)
- */
- public void run(IAction action) {
- if (mSelection instanceof IStructuredSelection) {
- for (Iterator<?> it = ((IStructuredSelection)mSelection).iterator(); it.hasNext();) {
- Object element = it.next();
- IProject project = null;
- if (element instanceof IProject) {
- project = (IProject)element;
- } else if (element instanceof IAdaptable) {
- project = (IProject)((IAdaptable)element).getAdapter(IProject.class);
- }
- if (project != null) {
- convertProject(project);
- }
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see IActionDelegate#selectionChanged(IAction, ISelection)
- */
- public void selectionChanged(IAction action, ISelection selection) {
- this.mSelection = selection;
- }
-
- /**
- * Toggles sample nature on a project
- *
- * @param project to have sample nature added or removed
- */
- private void convertProject(final IProject project) {
- new Job("Convert Project") {
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- if (monitor != null) {
- monitor.beginTask(String.format(
- "Convert %1$s to Android", project.getName()), 5);
- }
-
- IProjectDescription description = project.getDescription();
- String[] natures = description.getNatureIds();
-
- // check if the project already has the android nature.
- for (int i = 0; i < natures.length; ++i) {
- if (PlatformNature.ID.equals(natures[i])) {
- // we shouldn't be here as the visibility of the item
- // is dependent on the project.
- return new Status(Status.WARNING, AndroidPlatformPlugin.PLUGIN_ID,
- "Project is already an Android Platform Project");
- }
- }
-
- // add the platform nature
- String[] newNatures = new String[natures.length + 1];
- System.arraycopy(natures, 0, newNatures, 1, natures.length);
- newNatures[0] = PlatformNature.ID;
-
- // set the new nature list in the project
- description.setNatureIds(newNatures);
- project.setDescription(description, null);
-
- IJavaProject javaProject = JavaCore.create(project);
- IClasspathEntry[] entries = javaProject.getRawClasspath();
-
- int n = entries.length;
- IClasspathEntry[] newEntries = new IClasspathEntry[n + 1];
- System.arraycopy(entries, 0, newEntries, 0, n);
- newEntries[n] = PlatformClasspathContainerInitializer.getContainerEntry();
-
- javaProject.setRawClasspath(newEntries, monitor);
-
- return Status.OK_STATUS;
- } catch (JavaModelException e) {
- return e.getJavaModelStatus();
- } catch (CoreException e) {
- return e.getStatus();
- } finally {
- if (monitor != null) {
- monitor.done();
- }
- }
- }
- }.schedule();
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
deleted file mode 100644
index a54713c..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.ClasspathContainerInitializer;
-import org.eclipse.jdt.core.IClasspathContainer;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-/**
- * Classpath container initializer responsible for binding {@link PlatformClasspathContainer} to
- * {@link IProject}s. Because any projects with this container force Eclipse to load the
- * plugin, this is a hack to make sure the android platform plugin is launched as soon as an
- * android project is opened.
- */
-public class PlatformClasspathContainerInitializer extends ClasspathContainerInitializer {
-
- /** The container id for the android framework jar file */
- private final static String CONTAINER_ID = "com.android.ide.eclipse.platform.DUMMY_CONTAINER"; //$NON-NLS-1$
-
- public PlatformClasspathContainerInitializer() {
- // pass
- }
-
- /**
- * Binds a classpath container to a {@link IClasspathContainer} for a given project,
- * or silently fails if unable to do so.
- * @param containerPath the container path that is the container id.
- * @param the project to bind
- */
- @Override
- public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
- // pass
- }
-
- /**
- * Creates a new {@link IClasspathEntry} of type {@link IClasspathEntry#CPE_CONTAINER}
- * linking to the Android Framework.
- */
- public static IClasspathEntry getContainerEntry() {
- return JavaCore.newContainerEntry(new Path(CONTAINER_ID));
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java b/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
deleted file mode 100644
index 884dc58..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectNature;
-import org.eclipse.core.runtime.CoreException;
-
-/**
- * Project nature for the Android Projects.
- */
-public class PlatformNature implements IProjectNature {
-
- public final static String ID = "com.android.ide.eclipse.platform.PlatformNature"; //$NON-NLS-1$
-
- /** the project this nature object is associated with */
- private IProject mProject;
-
- /**
- * Configures this nature for its project. This is called by the workspace
- * when natures are added to the project using
- * <code>IProject.setDescription</code> and should not be called directly
- * by clients. The nature extension id is added to the list of natures
- * before this method is called, and need not be added here.
- *
- * Exceptions thrown by this method will be propagated back to the caller of
- * <code>IProject.setDescription</code>, but the nature will remain in
- * the project description.
- *
- * In this implementation there is nothing to be done, since there's no builder associated
- * with this nature.
- *
- * @see org.eclipse.core.resources.IProjectNature#configure()
- * @throws CoreException if configuration fails.
- */
- public void configure() throws CoreException {
- // pass
- }
-
- /**
- * De-configures this nature for its project. This is called by the
- * workspace when natures are removed from the project using
- * <code>IProject.setDescription</code> and should not be called directly
- * by clients. The nature extension id is removed from the list of natures
- * before this method is called, and need not be removed here.
- *
- * Exceptions thrown by this method will be propagated back to the caller of
- * <code>IProject.setDescription</code>, but the nature will still be
- * removed from the project description.
- *
- * In this implementation there is nothing to be done, since there's no builder associated
- * with this nature.
- *
- * @see org.eclipse.core.resources.IProjectNature#deconfigure()
- * @throws CoreException if configuration fails.
- */
- public void deconfigure() throws CoreException {
- // pass
- }
-
- /**
- * Returns the project to which this project nature applies.
- *
- * @return the project handle
- * @see org.eclipse.core.resources.IProjectNature#getProject()
- */
- public IProject getProject() {
- return mProject;
- }
-
- /**
- * Sets the project to which this nature applies. Used when instantiating
- * this project nature runtime. This is called by
- * <code>IProject.create()</code> or
- * <code>IProject.setDescription()</code> and should not be called
- * directly by clients.
- *
- * @param project the project to which this nature applies
- * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
- */
- public void setProject(IProject project) {
- mProject = project;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index a121266..266008c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -2,18 +2,17 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Android Plugin Tests
Bundle-SymbolicName: com.android.ide.eclipse.tests
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
Bundle-Activator: com.android.ide.eclipse.tests.AndroidTestPlugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.core.resources,
com.android.ide.eclipse.adt,
org.junit,
- com.android.ide.eclipse.common,
- com.android.ide.eclipse.editors,
org.eclipse.jdt.core,
org.eclipse.jdt.launching,
- org.eclipse.ui.views
+ org.eclipse.ui.views,
+ com.android.ide.eclipse.ddms
Eclipse-LazyStart: true
Bundle-Vendor: The Android Open Source Project
Bundle-ClassPath: kxml2-2.3.0.jar,
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
index 3202c67..42f8df0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 20078The Android Open Source Project
+ * Copyright (C) 2008 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
+ * 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
@@ -13,9 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
+package com.android.ide.eclipse.adt.wizards.newproject;
import java.io.File;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
index 49a853d..40cd636 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
@@ -5,7 +5,7 @@
* 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
+ * 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
@@ -13,10 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
-import com.android.ide.eclipse.adt.project.internal.NewProjectWizard;
+package com.android.ide.eclipse.adt.wizards.newproject;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
index 5315db8..98817c6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
@@ -5,7 +5,7 @@
* 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
+ * 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
@@ -16,10 +16,9 @@
package com.android.ide.eclipse.tests.functests.sampleProjects;
import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.internal.StubSampleProjectWizard;
+import com.android.ide.eclipse.adt.wizards.newproject.StubSampleProjectWizard;
import com.android.ide.eclipse.tests.FuncTestCase;
-
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
index 9d89d18..f3d9b79 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
@@ -14,21 +14,19 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.tests.AdtTestData;
-import junit.framework.TestCase;
-
-import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import junit.framework.TestCase;
+
/**
* Unit Test for {@link FrameworkClassLoader}.
*
@@ -51,7 +49,7 @@ public class AndroidJarLoaderTest extends TestCase {
/** Preloads classes. They should load just fine. */
public final void testPreLoadClasses() throws Exception {
- mFrameworkClassLoader.preLoadClasses("jar.example.", null); //$NON-NLS-1$
+ mFrameworkClassLoader.preLoadClasses("jar.example.", null, null); //$NON-NLS-1$
HashMap<String, Class<?>> map = getPrivateClassCache();
assertEquals(0, map.size());
HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -64,7 +62,7 @@ public class AndroidJarLoaderTest extends TestCase {
/** Preloads a class not in the JAR. Preloading does nothing in this case. */
public final void testPreLoadClasses_classNotFound() throws Exception {
- mFrameworkClassLoader.preLoadClasses("not.a.package.", null); //$NON-NLS-1$
+ mFrameworkClassLoader.preLoadClasses("not.a.package.", null, null); //$NON-NLS-1$
HashMap<String, Class<?>> map = getPrivateClassCache();
assertEquals(0, map.size());
HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -108,7 +106,7 @@ public class AndroidJarLoaderTest extends TestCase {
}
public final void testFindClassesDerivingFrom() throws Exception {
- HashMap<String, ArrayList<IClass>> found =
+ HashMap<String, ArrayList<IClassDescriptor>> found =
mFrameworkClassLoader.findClassesDerivingFrom("jar.example.", new String[] { //$NON-NLS-1$
"jar.example.Class1", //$NON-NLS-1$
"jar.example.Class2" }); //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
index 1a2ff9b..b66fcd6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
-import com.android.ide.eclipse.adt.resources.AndroidJarLoader.ClassWrapper;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.AndroidJarLoader.ClassWrapper;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
import com.android.ide.eclipse.common.resources.AttrsXmlParser;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -32,7 +32,7 @@ import java.util.TreeMap;
import junit.framework.TestCase;
/**
- * Test the inner private methods of FrameworkResourceParser.
+ * Test the inner private methods of PlatformDataParser.
*
* Convention: method names that start with an underscore are actually local wrappers
* that call private methods from {@link FrameworkResourceParser} using reflection.
@@ -47,9 +47,9 @@ public class LayoutParamsParserTest extends TestCase {
}
@Override
- public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+ public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
String rootPackage, String[] superClasses) throws ClassFormatError {
- return new HashMap<String, ArrayList<IClass>>();
+ return new HashMap<String, ArrayList<IClassDescriptor>>();
}
}
@@ -70,8 +70,8 @@ public class LayoutParamsParserTest extends TestCase {
mTopGroupClass = new ClassWrapper(mock_android.view.ViewGroup.class);
mTopLayoutParamsClass = new ClassWrapper(mock_android.view.ViewGroup.LayoutParams.class);
- mViewList = new ArrayList<IClass>();
- mGroupList = new ArrayList<IClass>();
+ mViewList = new ArrayList<IClassDescriptor>();
+ mGroupList = new ArrayList<IClassDescriptor>();
mViewMap = new TreeMap<String, ExtViewClassInfo>();
mGroupMap = new TreeMap<String, ExtViewClassInfo>();
mLayoutParamsMap = new HashMap<String, LayoutParamsInfo>();
@@ -131,16 +131,16 @@ public class LayoutParamsParserTest extends TestCase {
//---- access to private methods
/** Calls the private constructor of the parser */
- private FrameworkResourceParser _Constructor(String osJarPath) throws Exception {
- Constructor<FrameworkResourceParser> constructor =
- FrameworkResourceParser.class.getDeclaredConstructor(String.class);
+ private AndroidTargetParser _Constructor(String osJarPath) throws Exception {
+ Constructor<AndroidTargetParser> constructor =
+ AndroidTargetParser.class.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
return constructor.newInstance(osJarPath);
}
/** calls the private getLayoutClasses() of the parser */
private void _getLayoutClasses() throws Exception {
- Method method = FrameworkResourceParser.class.getDeclaredMethod("getLayoutClasses"); //$NON-NLS-1$
+ Method method = AndroidTargetParser.class.getDeclaredMethod("getLayoutClasses"); //$NON-NLS-1$
method.setAccessible(true);
method.invoke(mParser);
}
@@ -148,7 +148,7 @@ public class LayoutParamsParserTest extends TestCase {
/** calls the private addGroup() of the parser */
private ViewClassInfo _addGroup(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("addGroup", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (ViewClassInfo) method.invoke(mParser, new ClassWrapper(groupClass));
}
@@ -156,7 +156,7 @@ public class LayoutParamsParserTest extends TestCase {
/** calls the private addLayoutParams() of the parser */
private LayoutParamsInfo _addLayoutParams(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("addLayoutParams", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(groupClass));
}
@@ -164,17 +164,17 @@ public class LayoutParamsParserTest extends TestCase {
/** calls the private getLayoutParamsInfo() of the parser */
private LayoutParamsInfo _getLayoutParamsInfo(Class<?> layoutParamsClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("getLayoutParamsInfo", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(layoutParamsClass));
}
/** calls the private findLayoutParams() of the parser */
- private IClass _findLayoutParams(Class<?> groupClass) throws Exception {
+ private IClassDescriptor _findLayoutParams(Class<?> groupClass) throws Exception {
Method method = LayoutParamsParser.class.getDeclaredMethod("findLayoutParams", //$NON-NLS-1$
- IClass.class);
+ IClassDescriptor.class);
method.setAccessible(true);
- return (IClass) method.invoke(mParser, new ClassWrapper(groupClass));
+ return (IClassDescriptor) method.invoke(mParser, new ClassWrapper(groupClass));
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
index 521bb62..1427eee 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
@@ -216,9 +216,6 @@ public class UiElementPullParserTest extends TestCase {
} catch (XmlPullParserException e) {
e.printStackTrace();
assertTrue(false);
- } catch (IOException e) {
- e.printStackTrace();
- assertTrue(false);
}
}
diff --git a/eclipse/doBuild.sh b/eclipse/scripts/build_plugins.sh
index a0d8606..5f94ca0 100755
--- a/eclipse/doBuild.sh
+++ b/eclipse/scripts/build_plugins.sh
@@ -2,7 +2,7 @@
# build script for eclipse adt build on linux platform
#
-# Usage: doBuild <build_version>
+# Usage: development/tools/eclipse/scripts/build_plugins <build_version>
#
# It expects environment variable ECLIPSE_HOME to be defined to point to _your_
# version of Eclipse RCP (must have the WTP & GEF plugins available too.)
@@ -59,8 +59,10 @@ function dieWithUsage() {
HOST=`uname`
[ "$HOST" == "Linux" ] || die "ERROR: This script is currently only supported on Linux platform"
-# Check which directory this is invoked from
-[ "${PWD: -13}" == "tools/eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
+# Make sure this runs from the tools/eclipse plugin.
+D=`dirname "$0"`
+cd "$D/.."
+[ `basename "$PWD"` == "eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
# check for number of parameters
[ $# -lt 1 ] && dieWithUsage "ERROR: Not enough parameters"
@@ -86,6 +88,8 @@ if [ -z "$ECLIPSE_HOME" ]; then
[ -f "$PID_FILE" ] && ECLIPSE_PID=`cat "$PID_FILE"`
fi
+echo "PWD=`pwd`"
+echo "ECLIPSE_HOME=$ECLIPSE_HOME"
#
# -- Site parameters and Build version --
@@ -124,7 +128,7 @@ fi
# The "configuration directory" will hold the workspace for this build.
# If it contains old data the build may fail so we need to clean it first
# and create it if it doesn't exist.
-CONFIG_DIR="../../out/eclipse-configuration-$BUILD_VERSION"
+CONFIG_DIR="../../../out/eclipse-configuration-$BUILD_VERSION"
[ -d "$CONFIG_DIR" ] && rm -rfv "$CONFIG_DIR"
mkdir -p "$CONFIG_DIR"
@@ -173,8 +177,18 @@ echo " Build File: $BUILDFILE"
echo " Build Config: $BUILDCONFIG"
echo " Config Dir: $CONFIG_DIR"
+# clean input directories to make sure there's nothing left from previous run
+
+rm -fv *.properties *.xml
+find . -name "@*" | xargs rm -rfv
+
+# Now execute the ant runner
+
+set +e # don't stop on errors anymore, we want to catch there here
+
java \
-jar $LAUNCHER \
+ -data "$CONFIG_DIR" \
-configuration "$CONFIG_DIR" \
-application org.eclipse.ant.core.antRunner \
-buildfile $BUILDFILE \
@@ -183,6 +197,21 @@ java \
-DforceContextQualifier=$BUILD_VERSION \
-DECLIPSE_HOME=$ECLIPSE_HOME \
$SITE_PARAM
+RESULT=$?
+
+if [ "0" != "$RESULT" ]; then
+ echo "JAVA died with error code $RESULT"
+ echo "Dump of build config logs:"
+ for i in "$CONFIG_DIR"/*.log; do
+ if [ -f "$i" ]; then
+ echo "----------------------"
+ echo "--- $i"
+ echo "----------------------"
+ cat "$i"
+ echo
+ fi
+ done
+fi
#
# -- Cleanup
diff --git a/eclipse/scripts/build_server.sh b/eclipse/scripts/build_server.sh
index e30dbb8..39c8dcd 100755
--- a/eclipse/scripts/build_server.sh
+++ b/eclipse/scripts/build_server.sh
@@ -46,9 +46,10 @@ function die() {
}
function check_params() {
- # This needs to run from //device
- [ `basename "$PWD"` == "device" ] || \
- die "Please execute $0 from the //device directory, not $PWD"
+ # This needs to run from the top android directory
+ # Automatically CD to the top android directory, whatever its name
+ D=`dirname "$0"`
+ cd "$D/../../../../" && echo "Switched to directory $PWD"
# The current Eclipse build has some Linux dependency in its config files
[ `uname` == "Linux" ] || die "This must run from a Linux box."
@@ -60,14 +61,12 @@ function check_params() {
function build_libs() {
MAKE_OPT="-j8"
- echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api"
- make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils
+ echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api ninepatch sdklib sdkuilib"
+ make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib
}
function build_plugin {
- cd tools/eclipse/scripts
- ./create_all_symlinks.sh
- cd .. # cd back to tools/eclipse
+ development/tools/eclipse/scripts/create_all_symlinks.sh
# Qualifier is "v" followed by date/time in YYYYMMDDHHSS format and the optional
# build number.
@@ -90,7 +89,7 @@ function build_plugin {
[ -d "$DEST_DIR/$BUILD_PREFIX" ] || rm -rfv "$DEST_DIR/$BUILD_PREFIX"
# Perform the Eclipse build and move the result in $DEST_DIR/android-build
- ./doBuild.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
+ development/tools/eclipse/scripts/build_plugins.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
# Cleanup
[ -d "$QUALIFIER" ] && rm -rfv "$QUALIFIER"
diff --git a/eclipse/scripts/create_adt_symlinks.sh b/eclipse/scripts/create_adt_symlinks.sh
index 4974432..557c4d9 100755
--- a/eclipse/scripts/create_adt_symlinks.sh
+++ b/eclipse/scripts/create_adt_symlinks.sh
@@ -1,42 +1,50 @@
#!/bin/bash
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
set -e # fail early
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+DEST="development/tools/eclipse/plugins/com.android.ide.eclipse.adt"
+# computes "../.." from DEST to here (in /android)
+BACK=`echo $DEST | sed 's@[^/]*@..@g'`
+
+LIBS="sdkstats jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib"
+
+echo "make java libs ..."
+make -j3 showcommands $LIBS || die "ADT: Fail to build one of $LIBS."
+
+echo "Copying java libs to $DEST"
-cd ../plugins/com.android.ide.eclipse.adt
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/jarutils.jar .
- ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
+ for LIB in $LIBS; do
+ ln -svf $BACK/out/host/linux-x86/framework/$LIB.jar "$DEST/"
+ done
+ ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/jarutils.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
+ for LIB in $LIBS; do
+ ln -svf $BACK/out/host/darwin-x86/framework/$LIB.jar "$DEST/"
+ done
+ ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
- DEVICE_DIR="../../../.."
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands jarutils androidprefs ) || \
- die "Define javac and retry."
+elif [ "${HOST:0:6}" == "CYGWIN" ]; then
+ for LIB in $LIBS; do
+ cp -vf out/host/windows-x86/framework/$LIB.jar "$DEST/"
+ done
- for DIR in "$PWD" ; do
- echo "Copying java libs to $DIR"
- for JAR in jarutils.jar androidprefs.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- done
- done
+ if [ ! -f "$DEST/kxml2-2.3.0.jar" ]; then
+ cp -v "prebuilt/common/kxml2/kxml2-2.3.0.jar" "$DEST/"
+ fi
- chmod a+rx *.jar
+ chmod -v a+rx "$DEST"/*.jar
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh
index fc9766f..8508343 100755
--- a/eclipse/scripts/create_all_symlinks.sh
+++ b/eclipse/scripts/create_all_symlinks.sh
@@ -3,30 +3,25 @@
echo "### $0 executing"
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
-D="device/tools/eclipse/scripts"
-if [ -d "../$D" ]; then
- cd "../$D"
-else
- [ "${PWD: -28}" == "$D" ] || die "Please execute this from the $D directory"
-fi
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+DEST="development/tools/eclipse/scripts"
set -e # fail early
echo ; echo "### ADT ###" ; echo
-./create_adt_symlinks.sh "$*"
-echo ; echo "### COMMON ###" ; echo
-./create_common_symlinks.sh "$*"
-echo ; echo "### EDITORS ###" ; echo
-./create_editors_symlinks.sh "$*"
+$DEST/create_adt_symlinks.sh "$*"
echo ; echo "### DDMS ###" ; echo
-./create_ddms_symlinks.sh "$*"
+$DEST/create_ddms_symlinks.sh "$*"
echo ; echo "### TEST ###" ; echo
-./create_test_symlinks.sh "$*"
+$DEST/create_test_symlinks.sh "$*"
echo ; echo "### BRIDGE ###" ; echo
-./create_bridge_symlinks.sh "$*"
+$DEST/create_bridge_symlinks.sh "$*"
echo "### $0 done"
diff --git a/eclipse/scripts/create_bridge_symlinks.sh b/eclipse/scripts/create_bridge_symlinks.sh
index f01a89e..605ef63 100755
--- a/eclipse/scripts/create_bridge_symlinks.sh
+++ b/eclipse/scripts/create_bridge_symlinks.sh
@@ -1,47 +1,38 @@
#!/bin/bash
function die() {
- echo "Error: $*"
- exit 1
+ echo "Error: $*"
+ exit 1
}
set -e # fail early
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../../layoutlib
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- echo # nothing to do
+ echo # nothing to do
+
elif [ "$HOST" == "Darwin" ]; then
- echo # nothing to do
+ echo # nothing to do
+
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- if [ "x$1" == "x" ]; then
- echo "Usage: $0 sdk/tools/lib/"
- echo "Argument 1 should be the path to the jars you want to copy. "
- echo " e.g. android_sdk_windows_NNN/tools/lib/ "
- echo "This will be used to update layout.lib after it has been built here."
- exit 1
- fi
+ if [ "x$1" == "x" ] || [ `basename "$1"` != "layoutlib.jar" ]; then
+ echo "Usage: $0 sdk/platforms/xxx/data/layoutlib.jar"
+ echo "Argument 1 should be the path to the layoutlib.jar that should be updated."
+ exit 1
+ fi
- DEVICE_DIR="../../"
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands layoutlib ninepatch ) || \
- die "Define javac and retry."
+ LIBS="layoutlib ninepatch"
+ echo "Make java libs: $LIBS"
+ make -j3 showcommands $LIBS || die "Bridge: Failed to build one of $LIBS."
- for DIR in "$PWD" "$1" ; do
- echo "Copying java libs to $DIR"
- for JAR in ninepatch.jar layoutlib.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- done
- done
+ echo "Updating your SDK in $1"
+ cp -vf "out/host/windows-x86/framework/layoutlib.jar" "$1"
+ chmod -v a+rx "$1"
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
diff --git a/eclipse/scripts/create_common_symlinks.sh b/eclipse/scripts/create_common_symlinks.sh
deleted file mode 100755
index 7726afc..0000000
--- a/eclipse/scripts/create_common_symlinks.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-function die() {
- echo "Error: $*"
- exit 1
-}
-
-set -e # fail early
-
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../plugins/com.android.ide.eclipse.common
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/sdkstats.jar .
- ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
-elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/sdkstats.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-
- DEVICE_DIR="../../../.."
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 sdkstats androidprefs ) || \
- die "Define javac and retry."
-
- for DIR in "$PWD" ; do
- echo "Copying java libs to $DIR"
- for JAR in sdkstats.jar androidprefs.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
- chmod a+rx "$DIR/$JAR"
- done
- done
-
-else
- echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/eclipse/scripts/create_ddms_symlinks.sh b/eclipse/scripts/create_ddms_symlinks.sh
index 5b2e45b..276cf9b 100755
--- a/eclipse/scripts/create_ddms_symlinks.sh
+++ b/eclipse/scripts/create_ddms_symlinks.sh
@@ -4,58 +4,76 @@
# Run this from device/tools/eclipse/scripts
#----------------------------------------------------------------------------|
-CMD="ln -svf"
-DIR="ln -svf"
+set -e
+
HOST=`uname`
if [ "${HOST:0:6}" == "CYGWIN" ]; then
- CMD="cp -rvf"
- DIR="rsync -avW --delete-after"
+ # We can't use symlinks under Cygwin
+
+ function cpfile { # $1=dest $2=source
+ cp -fv $2 $1/
+ }
+
+ function cpdir() { # $1=dest $2=source
+ rsync -avW --delete-after $2 $1
+ }
+
+else
+ # For all other systems which support symlinks
+
+ # computes the "reverse" path, e.g. "a/b/c" => "../../.."
+ function back() {
+ echo $1 | sed 's@[^/]*@..@g'
+ }
+
+ function cpfile { # $1=dest $2=source
+ ln -svf `back $1`/$2 $1/
+ }
+
+ function cpdir() { # $1=dest $2=source
+ ln -svf `back $1`/$2 $1
+ }
fi
-cd ../plugins/com.android.ide.eclipse.ddms
-mkdir -p libs
-cd libs
-$CMD ../../../../../prebuilt/common/jfreechart/jcommon-1.0.12.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9-swt.jar .
-
-cd ../src/com/android
-$DIR ../../../../../../ddms/libs/ddmlib/src/com/android/ddmlib .
-$DIR ../../../../../../ddms/libs/ddmuilib/src/com/android/ddmuilib .
-
-# goes back to the icons directory
-cd ../../../icons/
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-attach.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-wait.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-error.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/device.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/emulator.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/heap.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/thread.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/empty.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/warning.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/d.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/e.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/i.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/v.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/w.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/add.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/delete.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/edit.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/save.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/push.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pull.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/clear.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/up.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/down.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/gc.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/halt.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/load.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/importBug.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/play.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pause.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/forward.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/backward.png .
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.ddms"
+
+DEST=$BASE/libs
+mkdir -p $DEST
+for i in prebuilt/common/jfreechart/*.jar; do
+ cpfile $DEST $i
+done
+DEST=$BASE/src/com/android
+mkdir -p $DEST
+for i in development/tools/ddms/libs/ddmlib/src/com/android/ddmlib \
+ development/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib ; do
+ cpdir $DEST $i
+done
+DEST=$BASE/icons
+mkdir -p $DEST
+for i in \
+ add.png \
+ backward.png \
+ clear.png \
+ d.png debug-attach.png debug-error.png debug-wait.png delete.png device.png down.png \
+ e.png edit.png empty.png emulator.png \
+ forward.png \
+ gc.png \
+ heap.png halt.png \
+ i.png importBug.png \
+ load.png \
+ pause.png play.png pull.png push.png \
+ save.png \
+ thread.png \
+ up.png \
+ v.png \
+ w.png warning.png ; do
+ cpfile $DEST development/tools/ddms/libs/ddmuilib/src/resources/images/$i
+done
diff --git a/eclipse/scripts/create_editors_symlinks.sh b/eclipse/scripts/create_editors_symlinks.sh
deleted file mode 100755
index 2f26ac4..0000000
--- a/eclipse/scripts/create_editors_symlinks.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-function die() {
- echo "Error: $*"
- exit 1
-}
-
-cd ../plugins/com.android.ide.eclipse.editors
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/layoutlib_api.jar .
- ln -svf ../../../../out/host/linux-x86/framework/layoutlib_utils.jar .
- ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
- ln -svf ../../../../out/host/linux-x86/framework/ninepatch.jar .
-elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_api.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_utils.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
- ln -svf ../../../../out/host/darwin-x86/framework/ninepatch.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- set -e # fail early
- DEVICE_DIR="../../../../"
- echo "make java libs ..."
- ( cd "$DEVICE_DIR" &&
- make -j3 showcommands layoutlib_api layoutlib_utils ninepatch ) || \
- die "Define javac and 'make layoutlib_api ninepatch' from device."
-
- echo "Copying java libs to $PWD"
- for JAR in layoutlib_api.jar layoutlib_utils.jar ninepatch.jar ; do
- cp -vf "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" .
- done
- if [ ! -f "./kxml2-2.3.0.jar" ]; then
- cp -v $DEVICE_DIR/prebuilt/common/kxml2/kxml2-2.3.0.jar .
- chmod -v a+rx *.jar
- fi
-
-else
- echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/eclipse/scripts/create_test_symlinks.sh b/eclipse/scripts/create_test_symlinks.sh
index 110539a..1479e04 100755
--- a/eclipse/scripts/create_test_symlinks.sh
+++ b/eclipse/scripts/create_test_symlinks.sh
@@ -1,24 +1,48 @@
#!/bin/bash
-cd ../plugins/com.android.ide.eclipse.tests
+
+set -e
+
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+# computes relative ".." paths from $1 to here (in /android)
+function back() {
+ echo $1 | sed 's@[^/]*@..@g'
+}
+
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.tests"
+DEST=$BASE
+BACK=`back $DEST`
+
+
HOST=`uname`
if [ "$HOST" == "Linux" ]; then
- ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
+ DIR="ln -svf"
+ ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "$HOST" == "Darwin" ]; then
- ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
+ DIR="ln -svf"
+ ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
- if [ "x$1" == "x" ]; then
- echo "Usage: $0 <path to jars>"
- echo "Argument 1 should be the path to the jars you want to copy. "
- echo " e.g. android_sdk_windows_NNN/tools/lib/ "
- echo "(since you can't rebuild them under Windows, you need prebuilt ones "
- echo " from an SDK drop or a Linux/Mac)"
- exit 1
- fi
- if [ ! -f "kxml2-2.3.0.jar" ]; then
- wget -O "kxml2-2.3.0.jar" "http://internap.dl.sourceforge.net/sourceforge/kxml/kxml2-2.3.0.jar"
- chmod a+rx *.jar
- fi
+ DIR="rsync -avW --delete-after"
+ JAR="kxml2-2.3.0.jar"
+ if [ ! -f "$DEST/$JAR" ]; then
+ # Get the jar from ADT if we can, otherwise download it.
+ if [ -f "$DEST/../com.android.ide.eclipse.adt/$JAR" ]; then
+ cp "$DEST/../com.android.ide.eclipse.adt/$JAR" "$DEST/$JAR"
+ else
+ wget -O "$DEST/$JAR" "http://internap.dl.sourceforge.net/sourceforge/kxml/$JAR"
+ fi
+ chmod a+rx "$DEST/$JAR"
+ fi
else
- echo "Unsupported platform ($HOST). Nothing done."
+ echo "Unsupported platform ($HOST). Nothing done."
fi
+# create link to ddmlib tests
+DEST=$BASE/unittests/com/android
+BACK=`back $DEST`
+$DIR $BACK/development/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib $DEST/
+
diff --git a/eclipse/scripts/update_version.sh b/eclipse/scripts/update_version.sh
new file mode 100644
index 0000000..a288965
--- /dev/null
+++ b/eclipse/scripts/update_version.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+OLD="$1"
+NEW="$2"
+
+# sanity check in input args
+if [ -z "$OLD" ] || [ -z "$NEW" ]; then
+ cat <<EOF
+Usage: $0 <old> <new>
+Changes the ADT plugin revision number.
+Example:
+ cd tools/eclipse
+ scripts/update_version.sh 0.1.2 0.2.3
+EOF
+ exit 1
+fi
+
+# sanity check on current dir
+if [ `basename "$PWD"` != "eclipse" ]; then
+ echo "Please run this from tools/eclipse."
+ exit 1
+fi
+
+# quote dots for regexps
+OLD="${OLD//./\.}"
+NEW="${NEW//./\.}"
+
+# Find all the files with the old pattern, except changes.txt and
+# p4 edit them. Skip that if there's no p4 in path.
+if which g4 1>/dev/null 2>/dev/null ; then
+ grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 5 g4 edit
+fi
+
+# Now find the same files but this time use sed to replace in-place with
+# the new pattern. Old files get backuped with the .old extension.
+grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 1 sed -i.old "s/$OLD/$NEW/g"
+
diff --git a/eclipse/sites/external/site.xml b/eclipse/sites/external/site.xml
index be123f6..e98a988 100644
--- a/eclipse/sites/external/site.xml
+++ b/eclipse/sites/external/site.xml
@@ -3,10 +3,7 @@
<description url="https://dl-ssl.google.com/android/eclipse/">
Update Site for Android Development Toolkit
</description>
- <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
- <category name="developer"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
<category name="developer"/>
</feature>
<category-def name="developer" label="Developer Tools">
diff --git a/eclipse/sites/internal/site.xml b/eclipse/sites/internal/site.xml
index 3263886..a7ef628 100644
--- a/eclipse/sites/internal/site.xml
+++ b/eclipse/sites/internal/site.xml
@@ -3,17 +3,10 @@
<description url="https://android.corp.google.com/adt/">
Update Site for Android Development Toolkit
</description>
- <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
<category name="developer"/>
</feature>
- <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
- <category name="developer"/>
- <category name="platform"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.platform_0.8.1.qualifier.jar" id="com.android.ide.eclipse.platform" version="0.8.1.qualifier">
- <category name="platform"/>
- </feature>
- <feature url="features/com.android.ide.eclipse.tests_0.8.1.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.8.1.qualifier">
+ <feature url="features/com.android.ide.eclipse.tests_0.9.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.9.0.qualifier">
<category name="test"/>
</feature>
<category-def name="developer" label="Application Developer Tools">
@@ -21,11 +14,6 @@
Features that add Android support to Eclipse for application developers.
</description>
</category-def>
- <category-def name="platform" label="Platform Developer Tools">
- <description>
- Features that add Android support to Eclipse for platform developers.
- </description>
- </category-def>
<category-def name="test" label="Plugin Developer Tests">
<description>
Tests for the other Android plugins