aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-03-09 13:08:53 -0800
committerAndroid Code Review <code-review@android.com>2011-03-09 13:08:53 -0800
commit57eb998efcd6031d01fc441ed0bd8b09c30b78c0 (patch)
treec2b5870a081f8fc00f01656d168b406a185d2c19
parent3a661854fa8921ee27de0ac7461f9c2b8fc744f5 (diff)
parentda02c18ad5b54d97a1fcfd5f6633062b0c873c22 (diff)
downloadsdk-57eb998efcd6031d01fc441ed0bd8b09c30b78c0.zip
sdk-57eb998efcd6031d01fc441ed0bd8b09c30b78c0.tar.gz
sdk-57eb998efcd6031d01fc441ed0bd8b09c30b78c0.tar.bz2
Merge "Resource management refactoring and clean-up."
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java25
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java12
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java34
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IIdResourceItem.java30
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IResourceRepository.java49
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceItem.java48
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Configurable.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Resource.java)23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ConfigurableResourceItem.java82
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResourceItem.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResources.java205
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/InlineResourceItem.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdResourceItem.java)38
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java111
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResourceItem.java91
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java891
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFile.java32
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFolder.java117
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceItem.java200
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java238
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceRepository.java644
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java41
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java163
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java90
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/FrameworkResourceRepository.java76
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/MarginChooser.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java46
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceContentProvider.java50
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceExplorerView.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceLabelProvider.java42
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java3
-rw-r--r--ide_common/src/com/android/ide/common/resources/ResourceResolver.java84
37 files changed, 1648 insertions, 1934 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
index 10ccd77..c28a561 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutReloadMonitor.java
@@ -37,6 +37,7 @@ import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -352,7 +353,7 @@ public final class LayoutReloadMonitor {
// now check that the file is *NOT* a layout file (those automatically trigger a layout
// reload and we don't want to do it twice.)
- List<ResourceType> resTypes = file.getResourceTypes();
+ Collection<ResourceType> resTypes = file.getResourceTypes();
// it's unclear why but there has been cases of resTypes being empty!
if (resTypes.size() > 0) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
index 3c5cea4..5e03b54 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
@@ -36,6 +36,7 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolder;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice;
import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager;
@@ -211,9 +212,9 @@ public class ConfigurationComposite extends Composite {
*/
void onRenderingTargetPostChange(IAndroidTarget target);
- ProjectResources getProjectResources();
- ProjectResources getFrameworkResources();
- ProjectResources getFrameworkResources(IAndroidTarget target);
+ ResourceRepository getProjectResources();
+ ResourceRepository getFrameworkResources();
+ ResourceRepository getFrameworkResources(IAndroidTarget target);
Map<ResourceType, Map<String, ResourceValue>> getConfiguredProjectResources();
Map<ResourceType, Map<String, ResourceValue>> getConfiguredFrameworkResources();
}
@@ -1121,12 +1122,12 @@ public class ConfigurationComposite extends Composite {
boolean hasLocale = false;
// get the languages from the project.
- ProjectResources project = mListener.getProjectResources();
+ ResourceRepository projectRes = mListener.getProjectResources();
// in cases where the opened file is not linked to a project, this could be null.
- if (project != null) {
+ if (projectRes != null) {
// now get the languages from the project.
- languages = project.getLanguages();
+ languages = projectRes.getLanguages();
for (String language : languages) {
hasLocale = true;
@@ -1134,7 +1135,7 @@ public class ConfigurationComposite extends Composite {
LanguageQualifier langQual = new LanguageQualifier(language);
// find the matching regions and add them
- SortedSet<String> regions = project.getRegions(language);
+ SortedSet<String> regions = projectRes.getRegions(language);
for (String region : regions) {
mLocaleCombo.add(
String.format("%1$s / %2$s", language, region)); //$NON-NLS-1$
@@ -1225,7 +1226,7 @@ public class ConfigurationComposite extends Composite {
return; // can't do anything w/o it.
}
- ProjectResources frameworkProject = mListener.getFrameworkResources(getRenderingTarget());
+ ResourceRepository frameworkRes = mListener.getFrameworkResources(getRenderingTarget());
mDisableUpdates++;
@@ -1237,10 +1238,10 @@ public class ConfigurationComposite extends Composite {
ArrayList<String> themes = new ArrayList<String>();
// get the themes, and languages from the Framework.
- if (frameworkProject != null) {
+ if (frameworkRes != null) {
// get the configured resources for the framework
Map<ResourceType, Map<String, ResourceValue>> frameworResources =
- frameworkProject.getConfiguredResources(getCurrentConfig());
+ frameworkRes.getConfiguredResources(getCurrentConfig());
if (frameworResources != null) {
// get the styles.
@@ -1269,9 +1270,9 @@ public class ConfigurationComposite extends Composite {
}
// now get the themes and languages from the project.
- ProjectResources project = mListener.getProjectResources();
+ ResourceRepository projectRes = mListener.getProjectResources();
// in cases where the opened file is not linked to a project, this could be null.
- if (project != null) {
+ if (projectRes != null) {
// get the configured resources for the project
Map<ResourceType, Map<String, ResourceValue>> configuredProjectRes =
mListener.getConfiguredProjectResources();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 9e0525e..858bfb8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -60,6 +60,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQ
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
@@ -541,7 +542,7 @@ public class GraphicalEditorPart extends EditorPart
public Map<ResourceType, Map<String, ResourceValue>> getConfiguredFrameworkResources() {
if (mConfiguredFrameworkRes == null && mConfigComposite != null) {
- ProjectResources frameworkRes = getFrameworkResources();
+ ResourceRepository frameworkRes = getFrameworkResources();
if (frameworkRes == null) {
AdtPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
@@ -559,9 +560,6 @@ public class GraphicalEditorPart extends EditorPart
if (mConfiguredProjectRes == null && mConfigComposite != null) {
ProjectResources project = getProjectResources();
- // make sure they are loaded
- project.loadAll();
-
// get the project resource values based on the current config
mConfiguredProjectRes = project.getConfiguredResources(
mConfigComposite.getCurrentConfig());
@@ -575,7 +573,7 @@ public class GraphicalEditorPart extends EditorPart
* configuration selection.
* @return the framework resources or null if not found.
*/
- public ProjectResources getFrameworkResources() {
+ public ResourceRepository getFrameworkResources() {
return getFrameworkResources(getRenderingTarget());
}
@@ -585,7 +583,7 @@ public class GraphicalEditorPart extends EditorPart
* @param target the target for which to return the framework resources.
* @return the framework resources or null if not found.
*/
- public ProjectResources getFrameworkResources(IAndroidTarget target) {
+ public ResourceRepository getFrameworkResources(IAndroidTarget target) {
if (target != null) {
AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
index f9e103a..3461d18 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeFinder.java
@@ -16,10 +16,11 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import static com.android.AndroidConstants.FD_RES_LAYOUT;
import static com.android.ide.eclipse.adt.AdtConstants.EXT_XML;
import static com.android.ide.eclipse.adt.AdtConstants.WS_LAYOUTS;
import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
-import static com.android.AndroidConstants.FD_RES_LAYOUT;
+import static com.android.resources.ResourceType.LAYOUT;
import static org.eclipse.core.resources.IResourceDelta.ADDED;
import static org.eclipse.core.resources.IResourceDelta.CHANGED;
@@ -30,10 +31,10 @@ import com.android.annotations.VisibleForTesting;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolder;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager.IResourceListener;
import com.android.ide.eclipse.adt.io.IFileWrapper;
@@ -62,6 +63,7 @@ import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -396,8 +398,8 @@ public class IncludeFinder {
private void scanProject() {
ProjectResources resources = ResourceManager.getInstance().getProjectResources(mProject);
if (resources != null) {
- ProjectResourceItem[] layouts = resources.getResources(ResourceType.LAYOUT);
- for (ProjectResourceItem layout : layouts) {
+ Collection<ResourceItem> layouts = resources.getResourceItemsOfType(LAYOUT);
+ for (ResourceItem layout : layouts) {
List<ResourceFile> sources = layout.getSourceFileList();
for (ResourceFile source : sources) {
updateFileIncludes(source, false);
@@ -419,7 +421,7 @@ public class IncludeFinder {
* @return true if we updated the includes for the resource file
*/
private boolean updateFileIncludes(ResourceFile resourceFile, boolean singleUpdate) {
- List<ResourceType> resourceTypes = resourceFile.getResourceTypes();
+ Collection<ResourceType> resourceTypes = resourceFile.getResourceTypes();
for (ResourceType type : resourceTypes) {
if (type == ResourceType.LAYOUT) {
ensureInitialized();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
index ce299e4..7a1e06e 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
@@ -38,8 +38,8 @@ import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewEleme
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SimpleElement;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
@@ -852,7 +852,7 @@ public class RulesEngine {
IProject project = editor.getProject();
if (project != null) {
// get the resource repository for this project and the system resources.
- IResourceRepository projectRepository =
+ ResourceRepository projectRepository =
ResourceManager.getInstance().getProjectResources(project);
Shell shell = AdtPlugin.getDisplay().getActiveShell();
if (shell == null) {
@@ -879,7 +879,7 @@ public class RulesEngine {
ResourceType type = ResourceType.getEnum(resourceTypeName);
if (project != null) {
// get the resource repository for this project and the system resources.
- IResourceRepository projectRepository = ResourceManager.getInstance()
+ ResourceRepository projectRepository = ResourceManager.getInstance()
.getProjectResources(project);
Shell shell = AdtPlugin.getDisplay().getActiveShell();
if (shell == null) {
@@ -887,7 +887,7 @@ public class RulesEngine {
}
AndroidTargetData data = editor.getTargetData();
- IResourceRepository systemRepository = data.getSystemResources();
+ ResourceRepository systemRepository = data.getFrameworkResources();
// open a resource chooser dialog for specified resource type.
ResourceChooser dlg = new ResourceChooser(project, type, projectRepository,
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
index b10d69b..1af04a8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
@@ -23,9 +23,9 @@ import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescrip
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.ui.ReferenceChooserDialog;
import com.android.ide.eclipse.adt.internal.ui.ResourceChooser;
@@ -48,6 +48,8 @@ import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -128,19 +130,19 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
IProject project = editor.getProject();
if (project != null) {
// get the resource repository for this project and the system resources.
- IResourceRepository projectRepository =
+ ResourceRepository projectRepository =
ResourceManager.getInstance().getProjectResources(project);
if (mType != null) {
// get the Target Data to get the system resources
AndroidTargetData data = editor.getTargetData();
- IResourceRepository systemRepository = data.getSystemResources();
+ ResourceRepository frameworkRepository = data.getFrameworkResources();
// open a resource chooser dialog for specified resource type.
ResourceChooser dlg = new ResourceChooser(project,
mType,
projectRepository,
- systemRepository,
+ frameworkRepository,
shell);
dlg.setCurrentResource(currentValue);
@@ -196,7 +198,7 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
*/
@Override
public String[] getPossibleValues(String prefix) {
- IResourceRepository repository = null;
+ ResourceRepository repository = null;
boolean isSystem = false;
UiElementNode uiNode = getUiParent();
@@ -212,15 +214,15 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
// If there's a prefix with "android:" in it, use the system resources
// Non-public framework resources are filtered out later.
AndroidTargetData data = editor.getTargetData();
- repository = data.getSystemResources();
+ repository = data.getFrameworkResources();
isSystem = true;
}
// Get list of potential resource types, either specific to this project
// or the generic list.
- ResourceType[] resTypes = (repository != null) ?
+ Collection<ResourceType> resTypes = (repository != null) ?
repository.getAvailableResourceTypes() :
- ResourceType.values();
+ EnumSet.allOf(ResourceType.class);
// Get the type name from the prefix, if any. It's any word before the / if there's one
String typeName = null;
@@ -265,18 +267,8 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
sb.append(typeName).append('/');
String base = sb.toString();
- if (isSystem) {
- AndroidTargetData targetData = editor.getTargetData();
- for (ResourceItem item : repository.getResources(resType)) {
- String name = item.getName();
- if (targetData == null || targetData.isPublicResource(resType, name)) {
- results.add(base + name);
- }
- }
- } else {
- for (ResourceItem item : repository.getResources(resType)) {
- results.add(base + item.getName());
- }
+ for (ResourceItem item : repository.getResourceItemsOfType(resType)) {
+ results.add(base + item.getName());
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
index efd95e2..5a2f39f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
@@ -47,6 +47,7 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolder;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.io.IFileWrapper;
@@ -790,7 +791,7 @@ public class Hyperlinks {
}
/** Return either the project resources or the framework resources (or null) */
- private static ProjectResources getResources(IProject project, boolean framework) {
+ private static ResourceRepository getResources(IProject project, boolean framework) {
if (framework) {
IAndroidTarget target = getTarget(project);
if (target == null) {
@@ -822,7 +823,7 @@ public class Hyperlinks {
}
// Look in the configuration folder: Search compatible configurations
- ProjectResources resources = getResources(project, false /* isFramework */);
+ ResourceRepository resources = getResources(project, false /* isFramework */);
FolderConfiguration configuration = getConfiguration();
if (configuration != null) { // Not the case when searching from Java files for example
List<ResourceFolder> folders = resources.getFolders(ResourceFolderType.LAYOUT);
@@ -1128,7 +1129,7 @@ public class Hyperlinks {
boolean isFramework = url.startsWith("@android"); //$NON-NLS-1$
- ProjectResources resources = getResources(project, isFramework);
+ ResourceRepository resources = getResources(project, isFramework);
if (resources == null) {
return null;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IIdResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IIdResourceItem.java
deleted file mode 100644
index acc4cf2..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IIdResourceItem.java
+++ /dev/null
@@ -1,30 +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.internal.resources;
-
-import com.android.resources.ResourceType;
-
-/**
- * Classes which implements this interface provides a method indicating the state of a resource of
- * type {@link ResourceType#ID}.
- */
-public interface IIdResourceItem {
- /**
- * Returns whether the ID resource has been declared inline inside another resource XML file.
- */
- public boolean isDeclaredInline();
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IResourceRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IResourceRepository.java
deleted file mode 100644
index 1abd9eb..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/IResourceRepository.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.internal.resources;
-
-import com.android.resources.ResourceType;
-
-/**
- * A repository of resources. This allows access to the resource by {@link ResourceType}.
- */
-public interface IResourceRepository {
-
- /**
- * Returns the present {@link ResourceType}s in the project.
- * @return an array containing all the type of resources existing in the project.
- */
- public abstract ResourceType[] getAvailableResourceTypes();
-
- /**
- * Returns an array of the existing resource for the specified type.
- * @param type the type of the resources to return
- */
- public abstract ResourceItem[] getResources(ResourceType type);
-
- /**
- * Returns whether resources of the specified type are present.
- * @param type the type of the resources to check.
- */
- public abstract boolean hasResources(ResourceType type);
-
- /**
- * Returns whether the repository is a system repository.
- */
- public abstract boolean isSystemRepository();
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
index 327bd89..568174c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.resources;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.resources.ResourceType;
@@ -29,11 +30,8 @@ public class ResourceHelper {
*/
public static String getXmlString(ResourceType type, ResourceItem resourceItem,
boolean system) {
- if (type == ResourceType.ID && resourceItem instanceof IIdResourceItem) {
- IIdResourceItem idResource = (IIdResourceItem)resourceItem;
- if (idResource.isDeclaredInline()) {
- return (system?"@android:":"@+") + type.getName() + "/" + resourceItem.getName(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
+ if (type == ResourceType.ID && resourceItem.isDeclaredInline()) {
+ return (system?"@android:":"@+") + type.getName() + "/" + resourceItem.getName(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return (system?"@android:":"@") + type.getName() + "/" + resourceItem.getName(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceItem.java
deleted file mode 100644
index c340ffe..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceItem.java
+++ /dev/null
@@ -1,48 +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.internal.resources;
-
-/**
- * Base class representing a Resource Item, as returned by a {@link IResourceRepository}.
- */
-public class ResourceItem implements Comparable<ResourceItem> {
-
- private final String mName;
-
- /**
- * Constructs a new ResourceItem
- * @param name the name of the resource as it appears in the XML and R.java files.
- */
- public ResourceItem(String name) {
- mName = name;
- }
-
- /**
- * Returns the name of the resource item.
- */
- public final String getName() {
- return mName;
- }
-
- /**
- * Compares the {@link ResourceItem} to another.
- * @param other the ResourceItem to be compared to.
- */
- public int compareTo(ResourceItem other) {
- return mName.compareTo(other.mName);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
index 543719b..3ad9d50 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
@@ -20,7 +20,7 @@ import static com.android.ide.eclipse.adt.AdtConstants.DOT_XML;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.resources.FolderTypeRelationship;
@@ -32,6 +32,7 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jface.dialogs.IInputValidator;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -160,9 +161,9 @@ public class ResourceNameValidator implements IInputValidator {
Set<String> existing = new HashSet<String>();
ResourceManager manager = ResourceManager.getInstance();
ProjectResources projectResources = manager.getProjectResources(project);
- ProjectResourceItem[] resources = projectResources.getResources(type);
- for (ProjectResourceItem resource : resources) {
- existing.add(resource.getName());
+ Collection<ResourceItem> items = projectResources.getResourceItemsOfType(type);
+ for (ResourceItem item : items) {
+ existing.add(item.getName());
}
boolean isFileType = isFileBasedResourceType(type);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Resource.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Configurable.java
index 0ad5c39..64dce73 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Resource.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/Configurable.java
@@ -19,28 +19,11 @@ package com.android.ide.eclipse.adt.internal.resources.manager;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
/**
- * Base class for file system resource items (Folders, Files).
+ * An object that is associated with a {@link FolderConfiguration}.
*/
-public abstract class Resource {
- private boolean mTouched = true;
-
+public interface Configurable {
/**
* Returns the {@link FolderConfiguration} for this object.
*/
- public abstract FolderConfiguration getConfiguration();
-
- /**
- * Indicates that the underlying file was changed.
- */
- public final void touch() {
- mTouched = true;
- }
-
- public final boolean isTouched() {
- return mTouched;
- }
-
- public final void resetTouch() {
- mTouched = false;
- }
+ public FolderConfiguration getConfiguration();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ConfigurableResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ConfigurableResourceItem.java
deleted file mode 100644
index 2a998f8..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ConfigurableResourceItem.java
+++ /dev/null
@@ -1,82 +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.internal.resources.manager;
-
-/**
- * Represents a resource item that can exist in multiple "alternate" versions.
- */
-public class ConfigurableResourceItem extends ProjectResourceItem {
-
- /**
- * Constructs a new Resource Item.
- * @param name the name of the resource as it appears in the XML and R.java files.
- */
- public ConfigurableResourceItem(String name) {
- super(name);
- }
-
- /**
- * Returns if the resource item has at least one non-default configuration.
- */
- public boolean hasAlternates() {
- for (ResourceFile file : mFiles) {
- if (file.getFolder().getConfiguration().isDefault() == false) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns whether the resource has a default version, with no qualifier.
- */
- public boolean hasDefault() {
- for (ResourceFile file : mFiles) {
- if (file.getFolder().getConfiguration().isDefault()) {
- return true;
- }
- }
-
- // We only want to return false if there's no default and more than 0 items.
- return (mFiles.size() == 0);
- }
-
- /**
- * Returns the number of alternate versions of this resource.
- */
- public int getAlternateCount() {
- int count = 0;
- for (ResourceFile file : mFiles) {
- if (file.getFolder().getConfiguration().isDefault() == false) {
- count++;
- }
- }
-
- return count;
- }
-
- /*
- * (non-Javadoc)
- * Returns whether the item can be edited directly (ie it does not have alternate versions).
- */
- @Override
- public boolean isEditableDirectly() {
- return hasAlternates() == false;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResourceItem.java
new file mode 100644
index 0000000..a0e79d9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResourceItem.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.resources.manager;
+
+/**
+ * A custom {@link ResourceItem} for resources provided by the framework.
+ *
+ * The main change is that {@link #isEditableDirectly()} returns false.
+ */
+class FrameworkResourceItem extends ResourceItem {
+
+ FrameworkResourceItem(String name) {
+ super(name);
+ }
+
+ @Override
+ public boolean isEditableDirectly() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "FrameworkResourceItem [mName=" + getName() + ", mFiles=" //$NON-NLS-1$ //$NON-NLS-2$
+ + getSourceFileList() + "]"; //$NON-NLS-1$
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResources.java
new file mode 100644
index 0000000..fc29dd9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/FrameworkResources.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.resources.manager;
+
+import static com.android.AndroidConstants.FD_RES_VALUES;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.io.IAbstractFile;
+import com.android.io.IAbstractFolder;
+import com.android.resources.ResourceType;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * Framework resources repository.
+ *
+ * This behaves the same as {@link ResourceRepository} except that it differentiates between
+ * resources that are public and non public.
+ * {@link #getResources(ResourceType)} and {@link #hasResourcesOfType(ResourceType)} only return
+ * public resources. This is typically used to display resource lists in the UI.
+ *
+ * {@link #getConfiguredResources(com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration)}
+ * returns all resources, even the non public ones so that this can be used for rendering.
+ */
+class FrameworkResources extends ResourceRepository {
+
+ /**
+ * Map of {@link ResourceType} to list of items. It is guaranteed to contain a list for all
+ * possible values of ResourceType.
+ */
+ protected final Map<ResourceType, List<ResourceItem>> mPublicResourceMap =
+ new EnumMap<ResourceType, List<ResourceItem>>(ResourceType.class);
+
+ FrameworkResources() {
+ super(true /*isFrameworkRepository*/);
+ }
+
+ /**
+ * Returns a {@link Collection} (always non null, but can be empty) of <b>public</b>
+ * {@link ResourceItem} matching a given {@link ResourceType}.
+ *
+ * @param type the type of the resources to return
+ * @return a collection of items, possible empty.
+ */
+ @Override
+ public List<ResourceItem> getResourceItemsOfType(ResourceType type) {
+ return mPublicResourceMap.get(type);
+ }
+
+ /**
+ * Returns whether the repository has <b>public</b> resources of a given {@link ResourceType}.
+ * @param type the type of resource to check.
+ * @return true if the repository contains resources of the given type, false otherwise.
+ */
+ @Override
+ public boolean hasResourcesOfType(ResourceType type) {
+ return mPublicResourceMap.get(type).size() > 0;
+ }
+
+ @Override
+ protected ResourceItem createResourceItem(String name) {
+ return new FrameworkResourceItem(name);
+ }
+
+ /**
+ * Reads the public.xml file in data/res/values/ for a given resource folder and builds up
+ * a map of public resources.
+ *
+ * This map is a subset of the full resource map that only contains framework resources
+ * that are public.
+ *
+ * @param osFrameworkResourcePath The root folder of the resources
+ */
+ void loadPublicResources(IAbstractFolder resFolder) {
+ IAbstractFolder valueFolder = resFolder.getFolder(FD_RES_VALUES);
+ if (valueFolder.exists() == false) {
+ return;
+ }
+
+ IAbstractFile publicXmlFile = valueFolder.getFile("public.xml"); //$NON-NLS-1$
+ if (publicXmlFile.exists()) {
+ Document document = null;
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ Reader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(publicXmlFile.getContents()));
+ InputSource is = new InputSource(reader);
+ factory.setNamespaceAware(true);
+ factory.setValidating(false);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ document = builder.parse(is);
+
+ ResourceType lastType = null;
+ String lastTypeName = "";
+
+ NodeList children = document.getDocumentElement().getChildNodes();
+ for (int i = 0, n = children.getLength(); i < n; i++) {
+ Node node = children.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ String name = element.getAttribute("name"); //$NON-NLS-1$
+ if (name.length() > 0) {
+ String typeName = element.getAttribute("type"); //$NON-NLS-1$
+ ResourceType type = null;
+ if (typeName.equals(lastTypeName)) {
+ type = lastType;
+ } else {
+ type = ResourceType.getEnum(typeName);
+ lastType = type;
+ lastTypeName = typeName;
+ }
+ if (type != null) {
+ List<ResourceItem> typeList = mResourceMap.get(type);
+
+ ResourceItem match = null;
+ if (typeList != null) {
+ for (ResourceItem item : typeList) {
+ if (name.equals(item.getName())) {
+ match = item;
+ break;
+ }
+ }
+ }
+
+ if (match != null) {
+ List<ResourceItem> publicList = mPublicResourceMap.get(type);
+ if (publicList == null) {
+ publicList = new ArrayList<ResourceItem>();
+ mPublicResourceMap.put(type, publicList);
+ }
+
+ publicList.add(match);
+ } else {
+ // log that there's a public resource that doesn't actually
+ // exist?
+ if (ResourceManager.DEBUG) {
+ System.out.println(String.format(
+ "No res matching public value %s/%s",
+ typeName, name));
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Can't read and parse public attribute list");
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // Nothing to be done here - we don't care if it closed or not.
+ }
+ }
+ }
+ }
+
+ // put unmodifiable list for all res type in the public resource map
+ // this will simplify access
+ for (ResourceType type : ResourceType.values()) {
+ List<ResourceItem> list = mPublicResourceMap.get(type);
+ if (list == null) {
+ list = Collections.emptyList();
+ } else {
+ list = Collections.unmodifiableList(list);
+ }
+
+ // put the new list in the map
+ mPublicResourceMap.put(type, list);
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/InlineResourceItem.java
index 8b142fb..6d1bd23 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/IdResourceItem.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/InlineResourceItem.java
@@ -16,39 +16,39 @@
package com.android.ide.eclipse.adt.internal.resources.manager;
-import com.android.ide.eclipse.adt.internal.resources.IIdResourceItem;
-import com.android.resources.ResourceType;
/**
- * Represents a resource item of type {@link ResourceType#ID}
+ * Represents a resource item that has been declared inline in another resource file.
+ *
+ * This covers the typical ID declaration of "@+id/foo", but does not cover normal value
+ * resources declared in strings.xml or other similar value files.
+ *
+ * This resource will return {@code true} for {@link #isDeclaredInline()} and {@code false} for
+ * {@link #isEditableDirectly()}.
*/
-public class IdResourceItem extends ProjectResourceItem implements IIdResourceItem {
-
- private final boolean mIsDeclaredInline;
+class InlineResourceItem extends ResourceItem {
/**
- * Constructs a new ResourceItem.
+ * Constructs a new inline ResourceItem.
* @param name the name of the resource as it appears in the XML and R.java files.
- * @param isDeclaredInline Whether this id was declared inline.
*/
- IdResourceItem(String name, boolean isDeclaredInline) {
+ InlineResourceItem(String name) {
super(name);
- mIsDeclaredInline = isDeclaredInline;
}
- /*
- * (non-Javadoc)
- * Returns whether the ID resource has been declared inline inside another resource XML file.
- */
+ @Override
public boolean isDeclaredInline() {
- return mIsDeclaredInline;
+ return true;
}
- /* (non-Javadoc)
- * Returns whether the item can be edited (ie, the id was not declared inline).
- */
@Override
public boolean isEditableDirectly() {
- return !mIsDeclaredInline;
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "InlineResourceItem [mName=" + getName() + ", mFiles=" //$NON-NLS-1$ //$NON-NLS-2$
+ + getSourceFileList() + "]"; //$NON-NLS-1$
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java
index 8f8e0d3..b37e7a2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java
@@ -26,14 +26,11 @@ import com.android.resources.ResourceType;
import org.xml.sax.SAXException;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
@@ -49,81 +46,79 @@ public final class MultiResourceFile extends ResourceFile implements IValueResou
private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance();
- private final Map<ResourceType, HashMap<String, ResourceValue>> mResourceItems =
- new EnumMap<ResourceType, HashMap<String, ResourceValue>>(ResourceType.class);
+ private final Map<ResourceType, Map<String, ResourceValue>> mResourceItems =
+ new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class);
- private List<ResourceType> mResourceTypeList = null;
+ private Collection<ResourceType> mResourceTypeList = null;
public MultiResourceFile(IAbstractFile file, ResourceFolder folder) {
super(file, folder);
}
@Override
- public List<ResourceType> getResourceTypes() {
- update();
-
- if (mResourceTypeList == null) {
- Set<ResourceType> keys = mResourceItems.keySet();
- mResourceTypeList = new ArrayList<ResourceType>();
- mResourceTypeList.addAll(keys);
- mResourceTypeList = Collections.unmodifiableList(mResourceTypeList);
- }
+ protected void load() {
+ // need to parse the file and find the content.
+ parseFile();
- return mResourceTypeList;
+ // create new ResourceItems for the new content.
+ mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet());
+
+ // create/update the resource items.
+ updateResourceItems();
}
@Override
- public boolean hasResources(ResourceType type) {
- update();
+ protected void update() {
+ // remove this file from all existing ResourceItem.
+ getFolder().getRepository().removeFile(mResourceTypeList, this);
- HashMap<String, ResourceValue> list = mResourceItems.get(type);
- return (list != null && list.size() > 0);
- }
+ // reset current content.
+ mResourceItems.clear();
- @Override
- public Collection<ProjectResourceItem> getResources(ResourceType type,
- ProjectResources projectResources) {
- update();
+ // need to parse the file and find the content.
+ parseFile();
- HashMap<String, ResourceValue> list = mResourceItems.get(type);
+ // create new ResourceItems for the new content.
+ mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet());
- ArrayList<ProjectResourceItem> items = new ArrayList<ProjectResourceItem>();
+ // create/update the resource items.
+ updateResourceItems();
+ }
- if (list != null) {
- Collection<ResourceValue> values = list.values();
- for (ResourceValue res : values) {
- ProjectResourceItem item = projectResources.findResourceItem(type, res.getName());
-
- if (item == null) {
- if (type == ResourceType.ID) {
- item = new IdResourceItem(res.getName(), false /* isDeclaredInline */);
- } else {
- item = new ConfigurableResourceItem(res.getName());
- }
- items.add(item);
- }
+ @Override
+ protected void dispose() {
+ // only remove this file from all existing ResourceItem.
+ getFolder().getRepository().removeFile(mResourceTypeList, this);
- item.add(this);
- }
- }
+ // don't need to touch the content, it'll get reclaimed as this objects disappear.
+ // In the mean time other objects may need to access it.
+ }
- return items;
+ @Override
+ public Collection<ResourceType> getResourceTypes() {
+ return mResourceTypeList;
}
- /**
- * Updates the Resource items if necessary.
- */
- private void update() {
- if (isTouched() == true) {
- // reset current content.
- mResourceItems.clear();
+ @Override
+ public boolean hasResources(ResourceType type) {
+ Map<String, ResourceValue> list = mResourceItems.get(type);
+ return (list != null && list.size() > 0);
+ }
- // need to parse the file and find the content.
- parseFile();
+ private void updateResourceItems() {
+ ResourceRepository repository = getRepository();
+ for (ResourceType type : mResourceTypeList) {
+ Map<String, ResourceValue> list = mResourceItems.get(type);
- resetTouch();
+ if (list != null) {
+ Collection<ResourceValue> values = list.values();
+ for (ResourceValue res : values) {
+ ResourceItem item = repository.getResourceItem(type, res.getName());
- mResourceTypeList = null;
+ // add this file to the list of files generating this resource item.
+ item.add(this);
+ }
+ }
}
}
@@ -147,7 +142,7 @@ public final class MultiResourceFile extends ResourceFile implements IValueResou
* @param value The value of the resource.
*/
public void addResourceValue(ResourceType resType, ResourceValue value) {
- HashMap<String, ResourceValue> list = mResourceItems.get(resType);
+ Map<String, ResourceValue> list = mResourceItems.get(resType);
// if the list does not exist, create it.
if (list == null) {
@@ -169,10 +164,8 @@ public final class MultiResourceFile extends ResourceFile implements IValueResou
@Override
public ResourceValue getValue(ResourceType type, String name) {
- update();
-
// get the list for the given type
- HashMap<String, ResourceValue> list = mResourceItems.get(type);
+ Map<String, ResourceValue> list = mResourceItems.get(type);
if (list != null) {
return list.get(name);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResourceItem.java
deleted file mode 100644
index 845a974..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResourceItem.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.android.ide.eclipse.adt.internal.resources.manager;
-
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
-import com.android.resources.ResourceType;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Base class for Resource Item coming from an Android Project.
- */
-public abstract class ProjectResourceItem extends ResourceItem {
-
- private final static Comparator<ResourceFile> sComparator = new Comparator<ResourceFile>() {
- public int compare(ResourceFile file1, ResourceFile file2) {
- // get both FolderConfiguration and compare them
- FolderConfiguration fc1 = file1.getFolder().getConfiguration();
- FolderConfiguration fc2 = file2.getFolder().getConfiguration();
-
- return fc1.compareTo(fc2);
- }
- };
-
- /**
- * List of files generating this ResourceItem.
- */
- protected final ArrayList<ResourceFile> mFiles = new ArrayList<ResourceFile>();
-
- /**
- * Constructs a new ResourceItem.
- * @param name the name of the resource as it appears in the XML and R.java files.
- */
- public ProjectResourceItem(String name) {
- super(name);
- }
-
- /**
- * Returns whether the resource item is editable directly.
- * <p/>
- * This is typically the case for resources that don't have alternate versions, or resources
- * of type {@link ResourceType#ID} that aren't declared inline.
- */
- public abstract boolean isEditableDirectly();
-
- /**
- * Adds a new version of this resource item, by adding its {@link ResourceFile}.
- * @param file the {@link ResourceFile} object.
- */
- protected void add(ResourceFile file) {
- mFiles.add(file);
- }
-
- /**
- * Reset the item by emptying its version list.
- */
- protected void reset() {
- mFiles.clear();
- }
-
- /**
- * Returns the sorted list of {@link ResourceItem} objects for this resource item.
- */
- public ResourceFile[] getSourceFileArray() {
- ArrayList<ResourceFile> list = new ArrayList<ResourceFile>();
- list.addAll(mFiles);
-
- Collections.sort(list, sComparator);
-
- return list.toArray(new ResourceFile[list.size()]);
- }
-
- /**
- * Returns the list of {@link ResourceItem} objects for this resource item.
- */
- public List<ResourceFile> getSourceFileList() {
- return Collections.unmodifiableList(mFiles);
- }
-
-
- /**
- * Replaces the content of the receiver with the ResourceItem received as parameter.
- * @param item
- */
- protected void replaceWith(ProjectResourceItem item) {
- mFiles.clear();
- mFiles.addAll(item.mFiles);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
index b7f406d..a6ee95d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
@@ -17,51 +17,37 @@
package com.android.ide.eclipse.adt.internal.resources.manager;
import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
-import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.io.IFolderWrapper;
-import com.android.io.IAbstractFolder;
-import com.android.resources.FolderTypeRelationship;
-import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.util.Pair;
-import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.Map.Entry;
/**
- * Represents the resources of a project. This is a file view of the resources, with handling
- * for the alternate resource types. For a compiled view use CompiledResources.
+ * Represents the resources of a project.
+ * On top of the regular {@link ResourceRepository} features it provides:
+ *<ul>
+ *<li>configured resources contain the resources coming from the libraries.</li>
+ *<li>resolution to and from resource integer (compiled value in R.java).</li>
+ *<li>handles resource integer for non existing values of type ID. This is used when rendering.</li>
+ *<li>layouts that have no been saved yet. This is handled by generating dynamic IDs
+ * on the fly.</li>
+ *</ul>
*/
-public class ProjectResources implements IResourceRepository {
+public class ProjectResources extends ResourceRepository {
private final static int DYNAMIC_ID_SEED_START = 0; // this should not conflict with any
// project IDs that start at a much higher
// value
- private final Map<ResourceFolderType, List<ResourceFolder>> mFolderMap =
- new EnumMap<ResourceFolderType, List<ResourceFolder>>(ResourceFolderType.class);
-
- private final Map<ResourceType, List<ProjectResourceItem>> mResourceMap =
- new EnumMap<ResourceType, List<ProjectResourceItem>>(ResourceType.class);
-
/** Map of (name, id) for resources of type {@link ResourceType#ID} coming from R.java */
private Map<ResourceType, Map<String, Integer>> mResourceValueMap;
/** Map of (id, [name, resType]) for all resources coming from R.java */
@@ -69,352 +55,38 @@ public class ProjectResources implements IResourceRepository {
/** Map of (int[], name) for styleable resources coming from R.java */
private Map<IntArrayWrapper, String> mStyleableValueToNameMap;
+ /**
+ * This list is used by {@link #getResourceValue(String, String)} when the resource
+ * query is an ID that doesn't exist (for example for ID automatically generated in
+ * layout files that are not saved yet).
+ */
private final Map<String, Integer> mDynamicIds = new HashMap<String, Integer>();
private int mDynamicSeed = DYNAMIC_ID_SEED_START;
- /** Cached list of {@link IdResourceItem}. This is mix of IdResourceItem created by
- * {@link MultiResourceFile} for ids coming from XML files under res/values and
- * {@link IdResourceItem} created manually, from the list coming from R.java */
- private final List<IdResourceItem> mIdResourceList = new ArrayList<IdResourceItem>();
-
- private final boolean mIsFrameworkRepository;
private final IProject mProject;
- private final IntArrayWrapper mWrapper = new IntArrayWrapper(null);
-
/**
* Makes a ProjectResources for a given <var>project</var>.
* @param project the project.
*/
public ProjectResources(IProject project) {
- mIsFrameworkRepository = false;
+ super(false /*isFrameworkRepository*/);
mProject = project;
}
/**
- * Makes a ProjectResource for a framework repository.
+ * Returns the resources values matching a given {@link FolderConfiguration}, this will
+ * include library dependency.
*
- * @see #isSystemRepository()
- */
- public ProjectResources() {
- mIsFrameworkRepository = true;
- mProject = null;
- }
-
- /**
- * Returns whether this ProjectResources is for a project or for a framework.
- */
- public boolean isSystemRepository() {
- return mIsFrameworkRepository;
- }
-
- /**
- * Adds a Folder Configuration to the project.
- * @param type The resource type.
- * @param config The resource configuration.
- * @param folder The workspace folder object.
- * @return the {@link ResourceFolder} object associated to this folder.
- */
- protected ResourceFolder add(ResourceFolderType type, FolderConfiguration config,
- IAbstractFolder folder) {
- // get the list for the resource type
- List<ResourceFolder> list = mFolderMap.get(type);
-
- if (list == null) {
- list = new ArrayList<ResourceFolder>();
-
- ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository);
- list.add(cf);
-
- mFolderMap.put(type, list);
-
- return cf;
- }
-
- // look for an already existing folder configuration.
- for (ResourceFolder cFolder : list) {
- if (cFolder.mConfiguration.equals(config)) {
- // config already exist. Nothing to be done really, besides making sure
- // the IFolder object is up to date.
- cFolder.mFolder = folder;
- return cFolder;
- }
- }
-
- // If we arrive here, this means we didn't find a matching configuration.
- // So we add one.
- ResourceFolder cf = new ResourceFolder(type, config, folder, mIsFrameworkRepository);
- list.add(cf);
-
- return cf;
- }
-
- /**
- * Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}.
- * @param type The type of the folder
- * @param folder the IFolder object.
- * @return the {@link ResourceFolder} that was removed, or null if no matches were found.
- */
- protected ResourceFolder removeFolder(ResourceFolderType type, IFolder folder) {
- // get the list of folders for the resource type.
- List<ResourceFolder> list = mFolderMap.get(type);
-
- if (list != null) {
- int count = list.size();
- for (int i = 0 ; i < count ; i++) {
- ResourceFolder resFolder = list.get(i);
- // this is only used for Eclipse stuff so we know it's an IFolderWrapper
- IFolderWrapper wrapper = (IFolderWrapper) resFolder.getFolder();
- if (wrapper.getIFolder().equals(folder)) {
- // we found the matching ResourceFolder. we need to remove it.
- list.remove(i);
-
- // we now need to invalidate this resource type.
- // The easiest way is to touch one of the other folders of the same type.
- if (list.size() > 0) {
- list.get(0).touch();
- } else {
- // if the list is now empty, and we have a single ResouceType out of this
- // ResourceFolderType, then we are done.
- // However, if another ResourceFolderType can generate similar ResourceType
- // than this, we need to update those ResourceTypes as well.
- // For instance, if the last "drawable-*" folder is deleted, we need to
- // refresh the ResourceItem associated with ResourceType.DRAWABLE.
- // Those can be found in ResourceFolderType.DRAWABLE but also in
- // ResourceFolderType.VALUES.
- // If we don't find a single folder to touch, then it's fine, as the top
- // level items (the list of generated resource types) is not cached
- // (for now)
-
- // get the lists of ResourceTypes generated by this ResourceFolderType
- List<ResourceType> resTypes =
- FolderTypeRelationship.getRelatedResourceTypes(type);
-
- // for each of those, make sure to find one folder to touch so that the
- // list of ResourceItem associated with the type is rebuilt.
- for (ResourceType resType : resTypes) {
- // get the list of folder that can generate this type
- List<ResourceFolderType> folderTypes =
- FolderTypeRelationship.getRelatedFolders(resType);
-
- // we only need to touch one folder in any of those (since it's one
- // folder per type, not per folder type).
- for (ResourceFolderType folderType : folderTypes) {
- List<ResourceFolder> resFolders = mFolderMap.get(folderType);
-
- if (resFolders != null && resFolders.size() > 0) {
- resFolders.get(0).touch();
- break;
- }
- }
- }
- }
-
- // we're done updating/touching, we can stop
- return resFolder;
- }
- }
- }
-
- return null;
- }
-
-
- /**
- * Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}.
- * @param type The {@link ResourceFolderType}
- */
- public List<ResourceFolder> getFolders(ResourceFolderType type) {
- return mFolderMap.get(type);
- }
-
- /* (non-Javadoc)
- * @see com.android.ide.eclipse.editors.resources.IResourceRepository#getAvailableResourceTypes()
- */
- public ResourceType[] getAvailableResourceTypes() {
- ArrayList<ResourceType> list = new ArrayList<ResourceType>();
-
- // For each key, we check if there's a single ResourceType match.
- // If not, we look for the actual content to give us the resource type.
-
- for (ResourceFolderType folderType : mFolderMap.keySet()) {
- List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(folderType);
- if (types.size() == 1) {
- // before we add it we check if it's not already present, since a ResourceType
- // could be created from multiple folders, even for the folders that only create
- // one type of resource (drawable for instance, can be created from drawable/ and
- // values/)
- if (list.indexOf(types.get(0)) == -1) {
- list.add(types.get(0));
- }
- } else {
- // there isn't a single resource type out of this folder, so we look for all
- // content.
- List<ResourceFolder> folders = mFolderMap.get(folderType);
- if (folders != null) {
- for (ResourceFolder folder : folders) {
- Collection<ResourceType> folderContent = folder.getResourceTypes();
-
- // then we add them, but only if they aren't already in the list.
- for (ResourceType folderResType : folderContent) {
- if (list.indexOf(folderResType) == -1) {
- list.add(folderResType);
- }
- }
- }
- }
- }
- }
-
- // in case ResourceType.ID haven't been added yet because there's no id defined
- // in XML, we check on the list of compiled id resources.
- if (list.indexOf(ResourceType.ID) == -1 && mResourceValueMap != null) {
- Map<String, Integer> map = mResourceValueMap.get(ResourceType.ID);
- if (map != null && map.size() > 0) {
- list.add(ResourceType.ID);
- }
- }
-
- // at this point the list is full of ResourceType defined in the files.
- // We need to sort it.
- Collections.sort(list);
-
- return list.toArray(new ResourceType[list.size()]);
- }
-
- /* (non-Javadoc)
- * @see com.android.ide.eclipse.editors.resources.IResourceRepository#getResources(com.android.ide.eclipse.common.resources.ResourceType)
- */
- public ProjectResourceItem[] getResources(ResourceType type) {
- checkAndUpdate(type);
-
- if (type == ResourceType.ID) {
- synchronized (mIdResourceList) {
- return mIdResourceList.toArray(new ProjectResourceItem[mIdResourceList.size()]);
- }
- }
-
- List<ProjectResourceItem> items = mResourceMap.get(type);
-
- return items.toArray(new ProjectResourceItem[items.size()]);
- }
-
- /* (non-Javadoc)
- * @see com.android.ide.eclipse.editors.resources.IResourceRepository#hasResources(com.android.ide.eclipse.common.resources.ResourceType)
- */
- public boolean hasResources(ResourceType type) {
- checkAndUpdate(type);
-
- if (type == ResourceType.ID) {
- synchronized (mIdResourceList) {
- return mIdResourceList.size() > 0;
- }
- }
-
- List<ProjectResourceItem> items = mResourceMap.get(type);
- return (items != null && items.size() > 0);
- }
-
- /**
- * Returns the {@link ResourceFolder} associated with a {@link IFolder}.
- * @param folder The {@link IFolder} object.
- * @return the {@link ResourceFolder} or null if it was not found.
- */
- public ResourceFolder getResourceFolder(IFolder folder) {
- for (List<ResourceFolder> list : mFolderMap.values()) {
- for (ResourceFolder resFolder : list) {
- // this is only used for Eclipse stuff so we know it's an IFolderWrapper
- IFolderWrapper wrapper = (IFolderWrapper) resFolder.getFolder();
- if (wrapper.getIFolder().equals(folder)) {
- return resFolder;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and
- * configuration.
- * <p/>This only works with files generating one resource named after the file (for instance,
- * layouts, bitmap based drawable, xml, anims).
- * @return the matching file or <code>null</code> if no match was found.
- */
- public ResourceFile getMatchingFile(String name, ResourceFolderType type,
- FolderConfiguration config) {
- // get the folders for the given type
- List<ResourceFolder> folders = mFolderMap.get(type);
-
- // look for folders containing a file with the given name.
- ArrayList<ResourceFolder> matchingFolders = new ArrayList<ResourceFolder>();
-
- // remove the folders that do not have a file with the given name.
- for (int i = 0 ; i < folders.size(); i++) {
- ResourceFolder folder = folders.get(i);
-
- if (folder.hasFile(name) == true) {
- matchingFolders.add(folder);
- }
- }
-
- // from those, get the folder with a config matching the given reference configuration.
- Resource match = findMatchingConfiguredResource(matchingFolders, config);
-
- // do we have a matching folder?
- if (match instanceof ResourceFolder) {
- // get the ResourceFile from the filename
- return ((ResourceFolder)match).getFile(name);
- }
-
- return null;
- }
-
- /**
- * Returns the list of source files for a given resource.
- * Optionally, if a {@link FolderConfiguration} is given, then only the best
- * match for this config is returned.
- *
- * @param type the type of the resource.
- * @param name the name of the resource.
- * @param referenceConfig an optional config for which only the best match will be returned.
- *
- * @return a list of files generating this resource or null if it was not found.
- */
- public List<ResourceFile> getSourceFiles(ResourceType type, String name,
- FolderConfiguration referenceConfig) {
-
- ProjectResourceItem[] resources = getResources(type);
-
- for (ProjectResourceItem item : resources) {
- if (name.equals(item.getName())) {
- if (referenceConfig != null) {
- Resource match = findMatchingConfiguredResource(item.getSourceFileList(),
- referenceConfig);
- if (match instanceof ResourceFile) {
- ArrayList<ResourceFile> list = new ArrayList<ResourceFile>();
- list.add((ResourceFile) match);
- return list;
- }
-
- return null;
- }
- return item.getSourceFileList();
- }
- }
-
- return null;
- }
-
- /**
- * Returns the resources values matching a given {@link FolderConfiguration}.
* @param referenceConfig the configuration that each value must match.
+ * @return a map with guaranteed to contain an entry for each {@link ResourceType}
*/
+ @Override
public Map<ResourceType, Map<String, ResourceValue>> getConfiguredResources(
FolderConfiguration referenceConfig) {
- Map<ResourceType, Map<String, ResourceValue>> map =
+ Map<ResourceType, Map<String, ResourceValue>> resultMap =
new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class);
// if the project contains libraries, we need to add the libraries resources here
@@ -435,25 +107,27 @@ public class ProjectResources implements IResourceRepository {
ProjectResources libRes = resMgr.getProjectResources(library);
if (libRes != null) {
- // make sure they are loaded
- libRes.loadAll();
+ // get the library resources, and only the library, not the dependencies
+ // so call doGetConfiguredResources() directly.
+ Map<ResourceType, Map<String, ResourceValue>> libMap =
+ libRes.doGetConfiguredResources(referenceConfig);
// we don't want to simply replace the whole map, but instead merge the
// content of any sub-map
- Map<ResourceType, Map<String, ResourceValue>> libMap =
- libRes.getConfiguredResources(referenceConfig);
+ for (Entry<ResourceType, Map<String, ResourceValue>> libEntry :
+ libMap.entrySet()) {
- for (Entry<ResourceType, Map<String, ResourceValue>> entry : libMap.entrySet()) {
// get the map currently in the result map for this resource type
- Map<String, ResourceValue> tempMap = map.get(entry.getKey());
+ Map<String, ResourceValue> tempMap = resultMap.get(libEntry.getKey());
if (tempMap == null) {
// since there's no current map for this type, just add the map
// directly coming from the library resources
- map.put(entry.getKey(), entry.getValue());
+ resultMap.put(libEntry.getKey(), libEntry.getValue());
} else {
// already a map for this type. add the resources from the
- // library.
- tempMap.putAll(entry.getValue());
+ // library, this will override existing value, which is why
+ // we loop in a specific library order.
+ tempMap.putAll(libEntry.getValue());
}
}
}
@@ -462,62 +136,21 @@ public class ProjectResources implements IResourceRepository {
}
// now the project resources themselves.
- // Don't blindly fill the map, instead check if there are sub-map already present
- // due to library resources.
-
- // special case for Id since there's a mix of compiled id (declared inline) and id declared
- // in the XML files.
- if (mIdResourceList.size() > 0) {
- Map<String, ResourceValue> idMap = map.get(ResourceType.ID);
-
- if (idMap == null) {
- idMap = new HashMap<String, ResourceValue>();
- map.put(ResourceType.ID, idMap);
- }
- for (IdResourceItem id : mIdResourceList) {
- // FIXME: cache the ResourceValue!
- idMap.put(id.getName(), new ResourceValue(ResourceType.ID, id.getName(),
- mIsFrameworkRepository));
- }
-
- }
-
- Set<ResourceType> keys = mResourceMap.keySet();
- for (ResourceType key : keys) {
- // we don't process ID resources since we already did it above.
- if (key != ResourceType.ID) {
- // get the local results
- Map<String, ResourceValue> localResMap = getConfiguredResource(key,
- referenceConfig);
-
- // check if a map for this type already exists
- Map<String, ResourceValue> resMap = map.get(key);
- if (resMap == null) {
- // just use the local results.
- map.put(key, localResMap);
- } else {
- // add to the library results.
- resMap.putAll(localResMap);
- }
+ Map<ResourceType, Map<String, ResourceValue>> thisProjectMap =
+ doGetConfiguredResources(referenceConfig);
+
+ // now merge the maps.
+ for (Entry<ResourceType, Map<String, ResourceValue>> entry : thisProjectMap.entrySet()) {
+ ResourceType type = entry.getKey();
+ Map<String, ResourceValue> typeMap = resultMap.get(type);
+ if (typeMap == null) {
+ resultMap.put(type, entry.getValue());
+ } else {
+ typeMap.putAll(entry.getValue());
}
}
- return map;
- }
-
- /**
- * Loads all the resources. Essentially this forces to load the values from the
- * {@link ResourceFile} objects to make sure they are up to date and loaded
- * in {@link #mResourceMap}.
- */
- public void loadAll() {
- // gets all the resource types available.
- ResourceType[] types = getAvailableResourceTypes();
-
- // loop on them and load them
- for (ResourceType type: types) {
- checkAndUpdate(type);
- }
+ return resultMap;
}
/**
@@ -572,55 +205,9 @@ public class ProjectResources implements IResourceRepository {
}
/**
- * Returns the sorted list of languages used in the resources.
- */
- public SortedSet<String> getLanguages() {
- SortedSet<String> set = new TreeSet<String>();
-
- Collection<List<ResourceFolder>> folderList = mFolderMap.values();
- for (List<ResourceFolder> folderSubList : folderList) {
- for (ResourceFolder folder : folderSubList) {
- FolderConfiguration config = folder.getConfiguration();
- LanguageQualifier lang = config.getLanguageQualifier();
- if (lang != null) {
- set.add(lang.getShortDisplayValue());
- }
- }
- }
-
- return set;
- }
-
- /**
- * Returns the sorted list of regions used in the resources with the given language.
- * @param currentLanguage the current language the region must be associated with.
- */
- public SortedSet<String> getRegions(String currentLanguage) {
- SortedSet<String> set = new TreeSet<String>();
-
- Collection<List<ResourceFolder>> folderList = mFolderMap.values();
- for (List<ResourceFolder> folderSubList : folderList) {
- for (ResourceFolder folder : folderSubList) {
- FolderConfiguration config = folder.getConfiguration();
-
- // get the language
- LanguageQualifier lang = config.getLanguageQualifier();
- if (lang != null && lang.getShortDisplayValue().equals(currentLanguage)) {
- RegionQualifier region = config.getRegionQualifier();
- if (region != null) {
- set.add(region.getShortDisplayValue());
- }
- }
- }
- }
-
- return set;
- }
-
- /**
* Resets the list of dynamic Ids. This list is used by
* {@link #getResourceValue(String, String)} when the resource query is an ID that doesn't
- * exist (for example for ID automatically generated in layout files that are not saved.
+ * exist (for example for ID automatically generated in layout files that are not saved yet.)
* <p/>This method resets those dynamic ID and must be called whenever the actual list of IDs
* change.
*/
@@ -631,262 +218,20 @@ public class ProjectResources implements IResourceRepository {
}
}
- /**
- * Returns a map of (resource name, resource value) for the given {@link ResourceType}.
- * <p/>The values returned are taken from the resource files best matching a given
- * {@link FolderConfiguration}.
- * @param type the type of the resources.
- * @param referenceConfig the configuration to best match.
- */
- private Map<String, ResourceValue> getConfiguredResource(ResourceType type,
- FolderConfiguration referenceConfig) {
- // get the resource item for the given type
- List<ProjectResourceItem> items = mResourceMap.get(type);
-
- // create the map
- HashMap<String, ResourceValue> map = new HashMap<String, ResourceValue>();
-
- for (ProjectResourceItem item : items) {
- // get the source files generating this resource
- List<ResourceFile> list = item.getSourceFileList();
-
- // look for the best match for the given configuration
- Resource match = findMatchingConfiguredResource(list, referenceConfig);
-
- if (match instanceof ResourceFile) {
- ResourceFile matchResFile = (ResourceFile)match;
-
- // get the value of this configured resource.
- ResourceValue value = matchResFile.getValue(type, item.getName());
-
- if (value != null) {
- map.put(item.getName(), value);
- }
- }
- }
-
- return map;
- }
-
- /**
- * Returns the best matching {@link Resource}.
- * @param resources the list of {@link Resource} to choose from.
- * @param referenceConfig the {@link FolderConfiguration} to match.
- * @see http://d.android.com/guide/topics/resources/resources-i18n.html#best-match
- */
- private Resource findMatchingConfiguredResource(List<? extends Resource> resources,
- FolderConfiguration referenceConfig) {
- //
- // 1: eliminate resources that contradict the reference configuration
- // 2: pick next qualifier type
- // 3: check if any resources use this qualifier, if no, back to 2, else move on to 4.
- // 4: eliminate resources that don't use this qualifier.
- // 5: if more than one resource left, go back to 2.
- //
- // The precedence of the qualifiers is more important than the number of qualifiers that
- // exactly match the device.
-
- // 1: eliminate resources that contradict
- ArrayList<Resource> matchingResources = new ArrayList<Resource>();
- for (int i = 0 ; i < resources.size(); i++) {
- Resource res = resources.get(i);
-
- if (res.getConfiguration().isMatchFor(referenceConfig)) {
- matchingResources.add(res);
- }
- }
-
- // if there is only one match, just take it
- if (matchingResources.size() == 1) {
- return matchingResources.get(0);
- } else if (matchingResources.size() == 0) {
- return null;
- }
-
- // 2. Loop on the qualifiers, and eliminate matches
- final int count = FolderConfiguration.getQualifierCount();
- for (int q = 0 ; q < count ; q++) {
- // look to see if one resource has this qualifier.
- // At the same time also record the best match value for the qualifier (if applicable).
-
- // The reference value, to find the best match.
- // Note that this qualifier could be null. In which case any qualifier found in the
- // possible match, will all be considered best match.
- ResourceQualifier referenceQualifier = referenceConfig.getQualifier(q);
-
- boolean found = false;
- ResourceQualifier bestMatch = null; // this is to store the best match.
- for (Resource res : matchingResources) {
- ResourceQualifier qualifier = res.getConfiguration().getQualifier(q);
- if (qualifier != null) {
- // set the flag.
- found = true;
-
- // Now check for a best match. If the reference qualifier is null ,
- // any qualifier is a "best" match (we don't need to record all of them.
- // Instead the non compatible ones are removed below)
- if (referenceQualifier != null) {
- if (qualifier.isBetterMatchThan(bestMatch, referenceQualifier)) {
- bestMatch = qualifier;
- }
- }
- }
- }
-
- // 4. If a resources has a qualifier at the current index, remove all the resources that
- // do not have one, or whose qualifier value does not equal the best match found above
- // unless there's no reference qualifier, in which case they are all considered
- // "best" match.
- if (found) {
- for (int i = 0 ; i < matchingResources.size(); ) {
- Resource res = matchingResources.get(i);
- ResourceQualifier qualifier = res.getConfiguration().getQualifier(q);
-
- if (qualifier == null) {
- // this resources has no qualifier of this type: rejected.
- matchingResources.remove(res);
- } else if (referenceQualifier != null && bestMatch != null &&
- bestMatch.equals(qualifier) == false) {
- // there's a reference qualifier and there is a better match for it than
- // this resource, so we reject it.
- matchingResources.remove(res);
- } else {
- // looks like we keep this resource, move on to the next one.
- i++;
- }
- }
-
- // at this point we may have run out of matching resources before going
- // through all the qualifiers.
- if (matchingResources.size() < 2) {
- break;
- }
- }
- }
-
- // Because we accept resources whose configuration have qualifiers where the reference
- // configuration doesn't, we can end up with more than one match. In this case, we just
- // take the first one.
- if (matchingResources.size() == 0) {
- return null;
- }
- return matchingResources.get(0);
- }
-
- /**
- * Checks if the list of {@link ResourceItem}s for the specified {@link ResourceType} needs
- * to be updated.
- * @param type the Resource Type.
- */
- private void checkAndUpdate(ResourceType type) {
- // get the list of folder that can output this type
- List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);
-
- for (ResourceFolderType folderType : folderTypes) {
- List<ResourceFolder> folders = mFolderMap.get(folderType);
-
- if (folders != null) {
- for (ResourceFolder folder : folders) {
- if (folder.isTouched()) {
- // if this folder is touched we need to update all the types that can
- // be generated from a file in this folder.
- // This will include 'type' obviously.
- List<ResourceType> resTypes =
- FolderTypeRelationship.getRelatedResourceTypes(folderType);
- for (ResourceType resType : resTypes) {
- update(resType);
- }
- return;
- }
- }
- }
- }
+ @Override
+ protected ResourceItem createResourceItem(String name) {
+ return new ResourceItem(name);
}
/**
- * Updates the list of {@link ResourceItem} objects associated with a {@link ResourceType}.
- * This will reset the touch status of all the folders that can generate this resource type.
- * @param type the Resource Type.
+ * Returns a dynamic integer for the given resource name, creating it if it doesn't
+ * already exist.
+ *
+ * @param name the name of the resource
+ * @return an integer.
+ *
+ * @see #resetDynamicIds()
*/
- private void update(ResourceType type) {
- // get the cache list, and lets make a backup
- List<ProjectResourceItem> items = mResourceMap.get(type);
- List<ProjectResourceItem> backup = new ArrayList<ProjectResourceItem>();
-
- if (items == null) {
- items = new ArrayList<ProjectResourceItem>();
- mResourceMap.put(type, items);
- } else {
- // backup the list
- backup.addAll(items);
-
- // we reset the list itself.
- items.clear();
- }
-
- // get the list of folder that can output this type
- List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);
-
- for (ResourceFolderType folderType : folderTypes) {
- List<ResourceFolder> folders = mFolderMap.get(folderType);
-
- if (folders != null) {
- for (ResourceFolder folder : folders) {
- items.addAll(folder.getResources(type, this));
- folder.resetTouch();
- }
- }
- }
-
- // now items contains the new list. We "merge" it with the backup list.
- // Basically, we need to keep the old instances of ResourceItem (where applicable),
- // but replace them by the content of the new items.
- // This will let the resource explorer keep the expanded state of the nodes whose data
- // is a ResourceItem object.
- if (backup.size() > 0) {
- // this is not going to change as we're only replacing instances.
- int count = items.size();
-
- for (int i = 0 ; i < count;) {
- // get the "new" item
- ProjectResourceItem item = items.get(i);
-
- // look for a similar item in the old list.
- ProjectResourceItem foundOldItem = null;
- for (ProjectResourceItem oldItem : backup) {
- if (oldItem.getName().equals(item.getName())) {
- foundOldItem = oldItem;
- break;
- }
- }
-
- if (foundOldItem != null) {
- // erase the data of the old item with the data from the new one.
- foundOldItem.replaceWith(item);
-
- // remove the old and new item from their respective lists
- items.remove(i);
- backup.remove(foundOldItem);
-
- // add the old item to the new list
- items.add(foundOldItem);
- } else {
- // this is a new item, we skip to the next object
- i++;
- }
- }
- }
-
- // if this is the ResourceType.ID, we create the actual list, from this list and
- // the compiled resource list.
- if (type == ResourceType.ID) {
- mergeIdResources();
- } else {
- // else this is the list that will actually be displayed, so we sort it.
- Collections.sort(items);
- }
- }
-
private Integer getDynamicId(String name) {
synchronized (mDynamicIds) {
Integer value = mDynamicIds.get(name);
@@ -900,24 +245,6 @@ public class ProjectResources implements IResourceRepository {
}
/**
- * Looks up an existing {@link ProjectResourceItem} by {@link ResourceType} and name.
- * @param type the Resource Type.
- * @param name the Resource name.
- * @return the existing ResourceItem or null if no match was found.
- */
- protected ProjectResourceItem findResourceItem(ResourceType type, String name) {
- List<ProjectResourceItem> list = mResourceMap.get(type);
-
- for (ProjectResourceItem item : list) {
- if (name.equals(item.getName())) {
- return item;
- }
- }
-
- return null;
- }
-
- /**
* Sets compiled resource information.
* @param resIdValueToNameMap a map of compiled resource id to resource name.
* The map is acquired by the {@link ProjectResources} object.
@@ -934,77 +261,67 @@ public class ProjectResources implements IResourceRepository {
mergeIdResources();
}
+ @Override
+ protected void postUpdate() {
+ super.postUpdate();
+ mergeIdResources();
+ }
+
/**
* Merges the list of ID resource coming from R.java and the list of ID resources
* coming from XML declaration into the cached list {@link #mIdResourceList}.
*/
void mergeIdResources() {
- // get the list of IDs coming from XML declaration. Those ids are present in
- // mCompiledIdResources already, so we'll need to use those instead of creating
- // new IdResourceItem
- List<ProjectResourceItem> xmlIdResources = mResourceMap.get(ResourceType.ID);
-
- synchronized (mIdResourceList) {
- // copy the currently cached items.
- ArrayList<IdResourceItem> oldItems = new ArrayList<IdResourceItem>();
- oldItems.addAll(mIdResourceList);
-
- // empty the current list
- mIdResourceList.clear();
-
- // get the list of compile id resources.
- Map<String, Integer> idMap = null;
- if (mResourceValueMap != null) {
- idMap = mResourceValueMap.get(ResourceType.ID);
- }
+ // get the current ID values
+ List<ResourceItem> resources = mResourceMap.get(ResourceType.ID);
- if (idMap == null) {
- if (xmlIdResources != null) {
- for (ProjectResourceItem resourceItem : xmlIdResources) {
- // check the actual class just for safety.
- if (resourceItem instanceof IdResourceItem) {
- mIdResourceList.add((IdResourceItem)resourceItem);
- }
- }
- }
- } else {
- // loop on the full list of id, and look for a match in the old list,
- // in the list coming from XML (in case a new XML item was created.)
-
- Set<String> idSet = idMap.keySet();
-
- idLoop: for (String idResource : idSet) {
- // first look in the XML list in case an id went from inline to XML declared.
- if (xmlIdResources != null) {
- for (ProjectResourceItem resourceItem : xmlIdResources) {
- if (resourceItem instanceof IdResourceItem &&
- resourceItem.getName().equals(idResource)) {
- mIdResourceList.add((IdResourceItem)resourceItem);
- continue idLoop;
- }
- }
- }
+ // get the ID values coming from the R class.
+ Map<String, Integer> rResources = mResourceValueMap.get(ResourceType.ID);
+
+ if (rResources != null) {
+ Map<String, Integer> copy;
- // if we haven't found it, look in the old items.
- int count = oldItems.size();
- for (int i = 0 ; i < count ; i++) {
- IdResourceItem resourceItem = oldItems.get(i);
- if (resourceItem.getName().equals(idResource)) {
- oldItems.remove(i);
- mIdResourceList.add(resourceItem);
- continue idLoop;
+ if (resources == null) {
+ resources = new ArrayList<ResourceItem>(rResources.entrySet().size());
+ mResourceMap.put(ResourceType.ID, resources);
+ copy = rResources;
+ } else {
+ // make a copy of the compiled Resources.
+ // As we loop on the full resources, we'll check with this copy map and remove
+ // from it all the resources we find in the full list.
+ // At the end, whatever is in the copy of the compile list is not in the full map,
+ // and should be added as inlined resource items.
+ copy = new HashMap<String, Integer>(rResources);
+
+ for (int i = 0 ; i < resources.size(); ) {
+ ResourceItem item = resources.get(i);
+ String name = item.getName();
+ if (item.isDeclaredInline()) {
+ // This ID is declared inline in the full resource map.
+ // Check if it's also in the compiled version, in which case we can keep it.
+ // Otherwise, if it doesn't exist in the compiled map, remove it from the
+ // full map.
+ // Since we're going to remove it from the copy map either way, we can use
+ // remove to test if it's there
+ if (copy.remove(name) != null) {
+ // there is a match in the compiled list, do nothing, keep current one.
+ i++;
+ } else {
+ // the ID is now gone, remove it from the list
+ resources.remove(i);
}
+ } else {
+ // not an inline item, remove it from the copy.
+ copy.remove(name);
+ i++;
}
-
- // if we haven't found it, it looks like it's a new id that was
- // declared inline.
- mIdResourceList.add(new IdResourceItem(idResource,
- true /* isDeclaredInline */));
}
}
- // now we sort the list
- Collections.sort(mIdResourceList);
+ // now add what's left in copy to the list
+ for (String name : copy.keySet()) {
+ resources.add(new InlineResourceItem(name));
+ }
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFile.java
index a6e10ae..151830e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFile.java
@@ -22,12 +22,11 @@ import com.android.io.IAbstractFile;
import com.android.resources.ResourceType;
import java.util.Collection;
-import java.util.List;
/**
* Represents a Resource file (a file under $Project/res/)
*/
-public abstract class ResourceFile extends Resource {
+public abstract class ResourceFile implements Configurable {
private final IAbstractFile mFile;
private final ResourceFolder mFolder;
@@ -37,11 +36,10 @@ public abstract class ResourceFile extends Resource {
mFolder = folder;
}
- /*
- * (non-Javadoc)
- * @see com.android.ide.eclipse.editors.resources.manager.Resource#getConfiguration()
- */
- @Override
+ protected abstract void load();
+ protected abstract void update();
+ protected abstract void dispose();
+
public FolderConfiguration getConfiguration() {
return mFolder.getConfiguration();
}
@@ -60,17 +58,21 @@ public abstract class ResourceFile extends Resource {
return mFolder;
}
+ public final ResourceRepository getRepository() {
+ return mFolder.getRepository();
+ }
+
/**
* Returns whether the resource is a framework resource.
*/
public final boolean isFramework() {
- return mFolder.isFramework();
+ return mFolder.getRepository().isFrameworkRepository();
}
/**
* Returns the list of {@link ResourceType} generated by the file. This is never null.
*/
- public abstract List<ResourceType> getResourceTypes();
+ public abstract Collection<ResourceType> getResourceTypes();
/**
* Returns whether the file generated a resource of a specific type.
@@ -79,18 +81,6 @@ public abstract class ResourceFile extends Resource {
public abstract boolean hasResources(ResourceType type);
/**
- * Get the list of {@link ProjectResourceItem} of a specific type generated by the file.
- * This method must make sure not to create duplicate.
- * @param type The type of {@link ProjectResourceItem} to return.
- * @param projectResources The global Project Resource object, allowing the implementation to
- * query for already existing {@link ProjectResourceItem}
- * @return The list of <b>new</b> {@link ProjectResourceItem}
- * @see ProjectResources#findResourceItem(ResourceType, String)
- */
- public abstract Collection<ProjectResourceItem> getResources(ResourceType type,
- ProjectResources projectResources);
-
- /**
* Returns the value of a resource generated by this file by {@link ResourceType} and name.
* <p/>If no resource match, <code>null</code> is returned.
* @param type the type of the resource.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFolder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFolder.java
index 40f6fbb..3d3cf70 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFolder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceFolder.java
@@ -16,32 +16,30 @@
package com.android.ide.eclipse.adt.internal.resources.manager;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
+import com.android.annotations.VisibleForTesting;
+import com.android.annotations.VisibleForTesting.Visibility;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
-import com.android.ide.eclipse.adt.io.IFileWrapper;
import com.android.io.IAbstractFile;
import com.android.io.IAbstractFolder;
import com.android.resources.FolderTypeRelationship;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Resource Folder class. Contains list of {@link ResourceFile}s,
- * the {@link FolderConfiguration}, and a link to the workspace {@link IFolder} object.
+ * the {@link FolderConfiguration}, and a link to the {@link IAbstractFolder} object.
*/
-public final class ResourceFolder extends Resource {
- ResourceFolderType mType;
- FolderConfiguration mConfiguration;
+public final class ResourceFolder implements Configurable {
+ final ResourceFolderType mType;
+ final FolderConfiguration mConfiguration;
IAbstractFolder mFolder;
ArrayList<ResourceFile> mFiles = null;
- private final boolean mIsFramework;
+ private final ResourceRepository mRepository;
+
/**
* Creates a new {@link ResourceFolder}
@@ -50,18 +48,19 @@ public final class ResourceFolder extends Resource {
* @param folder The associated {@link IAbstractFolder} object.
* @param isFrameworkRepository
*/
- public ResourceFolder(ResourceFolderType type, FolderConfiguration config,
- IAbstractFolder folder, boolean isFrameworkRepository) {
+ protected ResourceFolder(ResourceFolderType type, FolderConfiguration config,
+ IAbstractFolder folder, ResourceRepository repository) {
mType = type;
mConfiguration = config;
mFolder = folder;
- mIsFramework = isFrameworkRepository;
+ mRepository = repository;
}
/**
* Adds a {@link ResourceFile} to the folder.
* @param file The {@link ResourceFile}.
*/
+ @VisibleForTesting(visibility=Visibility.PROTECTED)
public void addFile(ResourceFile file) {
if (mFiles == null) {
mFiles = new ArrayList<ResourceFile>();
@@ -70,35 +69,21 @@ public final class ResourceFolder extends Resource {
mFiles.add(file);
}
- /**
- * Attempts to remove the {@link ResourceFile} associated with a specified {@link IFile}.
- * @param file the IFile object.
- * @return the {@link ResourceFile} that was removed.
- */
- public ResourceFile removeFile(IFile file) {
- if (mFiles != null) {
- int count = mFiles.size();
- for (int i = 0 ; i < count ; i++) {
- ResourceFile resFile = mFiles.get(i);
- if (resFile != null) {
- IAbstractFile abstractFile = resFile.getFile();
- if (abstractFile instanceof IFileWrapper) {
- IFile iFile = ((IFileWrapper)resFile.getFile()).getIFile();
- if (iFile != null && iFile.equals(file)) {
- mFiles.remove(i);
- touch();
- return resFile;
- }
- }
- }
- }
+ protected void removeFile(ResourceFile file) {
+ file.dispose();
+ mFiles.remove(file);
+ }
+
+ protected void dispose() {
+ for (ResourceFile file : mFiles) {
+ file.dispose();
}
- return null;
+ mFiles.clear();
}
/**
- * Returns the {@link IFolder} associated with this object.
+ * Returns the {@link IAbstractFolder} associated with this object.
*/
public IAbstractFolder getFolder() {
return mFolder;
@@ -111,11 +96,8 @@ public final class ResourceFolder extends Resource {
return mType;
}
- /**
- * Returns whether the folder is a framework resource folder.
- */
- public boolean isFramework() {
- return mIsFramework;
+ public ResourceRepository getRepository() {
+ return mRepository;
}
/**
@@ -126,7 +108,7 @@ public final class ResourceFolder extends Resource {
if (mFiles != null) {
for (ResourceFile file : mFiles) {
- List<ResourceType> types = file.getResourceTypes();
+ Collection<ResourceType> types = file.getResourceTypes();
// loop through those and add them to the main list,
// if they are not already present
@@ -141,11 +123,6 @@ public final class ResourceFolder extends Resource {
return list;
}
- /*
- * (non-Javadoc)
- * @see com.android.ide.eclipse.editors.resources.manager.Resource#getConfiguration()
- */
- @Override
public FolderConfiguration getConfiguration() {
return mConfiguration;
}
@@ -160,7 +137,7 @@ public final class ResourceFolder extends Resource {
/**
* Returns the {@link ResourceFile} matching a {@link IAbstractFile} object.
- * @param file The {@link IFile} object.
+ * @param file The {@link IAbstractFile} object.
* @return the {@link ResourceFile} or null if no match was found.
*/
public ResourceFile getFile(IAbstractFile file) {
@@ -175,27 +152,6 @@ public final class ResourceFolder extends Resource {
}
/**
- * Returns the {@link ResourceFile} matching a {@link IFile} object.
- * @param file The {@link IFile} object.
- * @return the {@link ResourceFile} or null if no match was found.
- */
- public ResourceFile getFile(IFile file) {
- if (mFiles != null) {
- for (ResourceFile f : mFiles) {
- IAbstractFile abstractFile = f.getFile();
- if (abstractFile instanceof IFileWrapper) {
- IFile iFile = ((IFileWrapper)f.getFile()).getIFile();
- if (iFile != null && iFile.equals(file)) {
- return f;
- }
- }
- }
- }
- return null;
- }
-
-
- /**
* Returns the {@link ResourceFile} matching a given name.
* @param filename The name of the file to return.
* @return the {@link ResourceFile} or <code>null</code> if no match was found.
@@ -240,27 +196,6 @@ public final class ResourceFolder extends Resource {
return false;
}
- /**
- * Get the list of {@link ResourceItem} of a specific type generated by all the files
- * in the folder.
- * This method must make sure not to create duplicates.
- * @param type The type of {@link ResourceItem} to return.
- * @param projectResources The global Project Resource object, allowing the implementation to
- * query for already existing {@link ResourceItem}
- * @return The list of <b>new</b> {@link ResourceItem}
- * @see ProjectResources#findResourceItem(ResourceType, String)
- */
- public Collection<ProjectResourceItem> getResources(ResourceType type,
- ProjectResources projectResources) {
- Collection<ProjectResourceItem> list = new ArrayList<ProjectResourceItem>();
- if (mFiles != null) {
- for (ResourceFile f : mFiles) {
- list.addAll(f.getResources(type, projectResources));
- }
- }
- return list;
- }
-
@Override
public String toString() {
return mFolder.toString();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceItem.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceItem.java
new file mode 100644
index 0000000..f826ed7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceItem.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.resources.manager;
+
+import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
+import com.android.resources.ResourceType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * An android resource.
+ *
+ * This is a representation of the resource, not of its value(s). It gives access to all
+ * the source files that generate this particular resource which then can be used to access
+ * the actual value(s).
+ *
+ * @see ResourceFile#getResources(ResourceType, ResourceRepository)
+ */
+public class ResourceItem implements Comparable<ResourceItem> {
+
+ private final static Comparator<ResourceFile> sComparator = new Comparator<ResourceFile>() {
+ public int compare(ResourceFile file1, ResourceFile file2) {
+ // get both FolderConfiguration and compare them
+ FolderConfiguration fc1 = file1.getFolder().getConfiguration();
+ FolderConfiguration fc2 = file2.getFolder().getConfiguration();
+
+ return fc1.compareTo(fc2);
+ }
+ };
+
+ private final String mName;
+
+ /**
+ * List of files generating this ResourceItem.
+ */
+ private final List<ResourceFile> mFiles = new ArrayList<ResourceFile>();
+
+ /**
+ * Constructs a new ResourceItem.
+ * @param name the name of the resource as it appears in the XML and R.java files.
+ */
+ public ResourceItem(String name) {
+ mName = name;
+ }
+
+ /**
+ * Returns the name of the resource.
+ */
+ public final String getName() {
+ return mName;
+ }
+
+ /**
+ * Compares the {@link ResourceItem} to another.
+ * @param other the ResourceItem to be compared to.
+ */
+ public int compareTo(ResourceItem other) {
+ return mName.compareTo(other.mName);
+ }
+
+ /**
+ * Returns whether the resource is editable directly.
+ * <p/>
+ * This is typically the case for resources that don't have alternate versions, or resources
+ * of type {@link ResourceType#ID} that aren't declared inline.
+ */
+ public boolean isEditableDirectly() {
+ return hasAlternates() == false;
+ }
+
+ /**
+ * Returns whether the ID resource has been declared inline inside another resource XML file.
+ * If the resource type is not {@link ResourceType#ID}, this will always return {@code false}.
+ */
+ public boolean isDeclaredInline() {
+ return false;
+ }
+
+ /**
+ * Adds a new source file.
+ * @param file the source file.
+ */
+ protected void add(ResourceFile file) {
+ mFiles.add(file);
+ }
+
+ /**
+ * Removes a file from the list of source files.
+ * @param file the file to remove
+ */
+ protected void removeFile(ResourceFile file) {
+ mFiles.remove(file);
+ }
+
+ /**
+ * Returns {@code true} if the item has no source file.
+ * @return
+ */
+ protected boolean hasNoSourceFile() {
+ return mFiles.size() == 0;
+ }
+
+ /**
+ * Reset the item by emptying its source file list.
+ */
+ protected void reset() {
+ mFiles.clear();
+ }
+
+ /**
+ * Returns the sorted list of {@link ResourceItem} objects for this resource item.
+ */
+ public ResourceFile[] getSourceFileArray() {
+ ArrayList<ResourceFile> list = new ArrayList<ResourceFile>();
+ list.addAll(mFiles);
+
+ Collections.sort(list, sComparator);
+
+ return list.toArray(new ResourceFile[list.size()]);
+ }
+
+ /**
+ * Returns the list of source file for this resource.
+ */
+ public List<ResourceFile> getSourceFileList() {
+ return Collections.unmodifiableList(mFiles);
+ }
+
+ /**
+ * Returns if the resource has at least one non-default version.
+ *
+ * @see ResourceFile#getConfiguration()
+ * @see FolderConfiguration#isDefault()
+ */
+ public boolean hasAlternates() {
+ for (ResourceFile file : mFiles) {
+ if (file.getFolder().getConfiguration().isDefault() == false) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns whether the resource has a default version, with no qualifier.
+ *
+ * @see ResourceFile#getConfiguration()
+ * @see FolderConfiguration#isDefault()
+ */
+ public boolean hasDefault() {
+ for (ResourceFile file : mFiles) {
+ if (file.getFolder().getConfiguration().isDefault()) {
+ return true;
+ }
+ }
+
+ // We only want to return false if there's no default and more than 0 items.
+ return (mFiles.size() == 0);
+ }
+
+ /**
+ * Returns the number of alternate versions for this resource.
+ *
+ * @see ResourceFile#getConfiguration()
+ * @see FolderConfiguration#isDefault()
+ */
+ public int getAlternateCount() {
+ int count = 0;
+ for (ResourceFile file : mFiles) {
+ if (file.getFolder().getConfiguration().isDefault() == false) {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ @Override
+ public String toString() {
+ return "ResourceItem [mName=" + mName + ", mFiles=" + mFiles + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
index c039f6b..1d3c709 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
@@ -17,6 +17,8 @@
package com.android.ide.eclipse.adt.internal.resources.manager;
import com.android.AndroidConstants;
+import com.android.annotations.VisibleForTesting;
+import com.android.annotations.VisibleForTesting.Visibility;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
@@ -24,6 +26,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQua
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFolderListener;
import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener;
+import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener;
import com.android.ide.eclipse.adt.io.IFileWrapper;
import com.android.ide.eclipse.adt.io.IFolderWrapper;
import com.android.io.FolderWrapper;
@@ -70,6 +73,7 @@ import java.util.List;
* @see ProjectResources
*/
public final class ResourceManager {
+ public final static boolean DEBUG = false;
private final static ResourceManager sThis = new ResourceManager();
@@ -114,7 +118,9 @@ public final class ResourceManager {
* @param monitor The global project monitor
*/
public static void setup(GlobalProjectMonitor monitor) {
+ monitor.addResourceEventListener(sThis.mResourceEventListener);
monitor.addProjectListener(sThis.mProjectListener);
+
int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED;
monitor.addFolderListener(sThis.mFolderListener, mask);
monitor.addFileListener(sThis.mFileListener, mask);
@@ -160,6 +166,40 @@ public final class ResourceManager {
}
}
+ private class ResourceEventListener implements IResourceEventListener {
+ private final List<IProject> mChangedProjects = new ArrayList<IProject>();
+
+ public void resourceChangeEventEnd() {
+ for (IProject project : mChangedProjects) {
+ ProjectResources resources;
+ synchronized (mMap) {
+ resources = mMap.get(project);
+ }
+
+ resources.postUpdate();
+ }
+
+ mChangedProjects.clear();
+ }
+
+ public void resourceChangeEventStart() {
+ // pass
+ }
+
+ void addProject(IProject project) {
+ if (mChangedProjects.contains(project) == false) {
+ mChangedProjects.add(project);
+ }
+ }
+ }
+
+ /**
+ * Delegate listener for resource changes. This is called before and after any calls to the
+ * project and file listeners (for a given resource change event).
+ */
+ private ResourceEventListener mResourceEventListener = new ResourceEventListener();
+
+
/**
* Implementation of the {@link IFolderListener} as an internal class so that the methods
* do not appear in the public API of {@link ResourceManager}.
@@ -179,6 +219,8 @@ public final class ResourceManager {
return;
}
+ mResourceEventListener.addProject(project);
+
switch (kind) {
case IResourceDelta.ADDED:
// checks if the folder is under res.
@@ -207,13 +249,13 @@ public final class ResourceManager {
}
break;
case IResourceDelta.CHANGED:
+ // only call the listeners.
synchronized (mMap) {
resources = mMap.get(folder.getProject());
}
if (resources != null) {
ResourceFolder resFolder = resources.getResourceFolder(folder);
if (resFolder != null) {
- resFolder.touch();
notifyListenerOnFolderChange(project, resFolder, kind);
}
}
@@ -227,7 +269,8 @@ public final class ResourceManager {
ResourceFolderType type = ResourceFolderType.getFolderType(
folder.getName());
- ResourceFolder removedFolder = resources.removeFolder(type, folder);
+ ResourceFolder removedFolder = resources.removeFolder(type,
+ new IFolderWrapper(folder));
if (removedFolder != null) {
notifyListenerOnFolderChange(project, removedFolder, kind);
}
@@ -255,8 +298,6 @@ public final class ResourceManager {
* @see IFileListener#fileChanged
*/
public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
- ProjectResources resources;
-
final IProject project = file.getProject();
try {
@@ -268,80 +309,39 @@ public final class ResourceManager {
return;
}
- switch (kind) {
- case IResourceDelta.ADDED:
- // checks if the file is under res/something.
- IPath path = file.getFullPath();
-
- if (path.segmentCount() == 4) {
- if (isInResFolder(path)) {
- // get the project and its resources
- synchronized (mMap) {
- resources = mMap.get(project);
- }
-
- IContainer container = file.getParent();
- if (container instanceof IFolder && resources != null) {
-
- ResourceFolder folder = resources.getResourceFolder(
- (IFolder)container);
-
- if (folder != null) {
- ResourceFile resFile = processFile(
- new IFileWrapper(file), folder);
- notifyListenerOnFileChange(project, resFile, kind);
- }
- }
- }
- }
- break;
- case IResourceDelta.CHANGED:
- // try to find a matching ResourceFile
- synchronized (mMap) {
- resources = mMap.get(project);
- }
- if (resources != null) {
- IContainer container = file.getParent();
- if (container instanceof IFolder) {
- ResourceFolder resFolder = resources.getResourceFolder(
- (IFolder)container);
+ // get the project resources
+ ProjectResources resources;
+ synchronized (mMap) {
+ resources = mMap.get(project);
+ }
- // we get the delete on the folder before the file, so it is possible
- // the associated ResourceFolder doesn't exist anymore.
- if (resFolder != null) {
- // get the resourceFile, and touch it.
- ResourceFile resFile = resFolder.getFile(file);
- if (resFile != null) {
- resFile.touch();
- notifyListenerOnFileChange(project, resFile, kind);
- }
- }
- }
- }
- break;
- case IResourceDelta.REMOVED:
- // try to find a matching ResourceFile
- synchronized (mMap) {
- resources = mMap.get(project);
- }
- if (resources != null) {
- IContainer container = file.getParent();
- if (container instanceof IFolder) {
- ResourceFolder resFolder = resources.getResourceFolder(
- (IFolder)container);
+ if (resources == null) {
+ return;
+ }
- // we get the delete on the folder before the file, so it is possible
- // the associated ResourceFolder doesn't exist anymore.
- if (resFolder != null) {
- // remove the file
- ResourceFile resFile = resFolder.removeFile(file);
- if (resFile != null) {
- notifyListenerOnFileChange(project, resFile, kind);
- }
- }
+ // checks if the file is under res/something.
+ IPath path = file.getFullPath();
+
+ if (path.segmentCount() == 4) {
+ if (isInResFolder(path)) {
+ IContainer container = file.getParent();
+ if (container instanceof IFolder) {
+
+ ResourceFolder folder = resources.getResourceFolder(
+ (IFolder)container);
+
+ // folder can be null as when the whole folder is deleted, the
+ // REMOVED event for the folder comes first. In this case, the
+ // folder will have taken care of things.
+ if (folder != null) {
+ ResourceFile resFile = processFile(
+ new IFileWrapper(file),
+ folder,
+ kind);
+ notifyListenerOnFileChange(project, resFile, kind);
}
}
- break;
+ }
}
}
};
@@ -413,15 +413,16 @@ public final class ResourceManager {
* Loads and returns the resources for a given {@link IAndroidTarget}
* @param androidTarget the target from which to load the framework resources
*/
- public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
+ public ResourceRepository loadFrameworkResources(IAndroidTarget androidTarget) {
String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
FolderWrapper frameworkRes = new FolderWrapper(osResourcesPath);
if (frameworkRes.exists()) {
- ProjectResources resources = new ProjectResources();
+ FrameworkResources resources = new FrameworkResources();
try {
loadResources(resources, frameworkRes);
+ resources.loadPublicResources(frameworkRes);
return resources;
} catch (IOException e) {
// since we test that folders are folders, and files are files, this shouldn't
@@ -433,7 +434,7 @@ public final class ResourceManager {
}
/**
- * Loads the resources from a folder, and fills the given {@link ProjectResources}.
+ * Loads the resources from a folder, and fills the given {@link ResourceRepository}.
* <p/>
* This is mostly a utility method that should not be used to process actual Eclipse projects
* (Those are loaded with {@link #createProject(IProject)} for new project or
@@ -447,13 +448,14 @@ public final class ResourceManager {
* setting rendering tests.
*
*
- * @param resources The {@link ProjectResources} files to load. It is expected that the
- * framework flag has been properly setup. This is filled up with the content of the folder.
+ * @param resources The {@link ResourceRepository} files to fill.
+ * This is filled up with the content of the folder.
* @param rootFolder The folder to read the resources from. This is the top level
* resource folder (res/)
* @throws IOException
*/
- public void loadResources(ProjectResources resources, IAbstractFolder rootFolder)
+ @VisibleForTesting(visibility=Visibility.PRIVATE)
+ public void loadResources(ResourceRepository resources, IAbstractFolder rootFolder)
throws IOException {
IAbstractResource[] files = rootFolder.listMembers();
for (IAbstractResource file : files) {
@@ -467,15 +469,12 @@ public final class ResourceManager {
for (IAbstractResource childRes : children) {
if (childRes instanceof IAbstractFile) {
- processFile((IAbstractFile) childRes, resFolder);
+ processFile((IAbstractFile) childRes, resFolder, IResourceDelta.ADDED);
}
}
}
}
}
-
- // now that we have loaded the files, we need to force load the resources from them
- resources.loadAll();
}
/**
@@ -522,7 +521,8 @@ public final class ResourceManager {
if (fileRes.getType() == IResource.FILE) {
IFile file = (IFile)fileRes;
- processFile(new IFileWrapper(file), resFolder);
+ processFile(new IFileWrapper(file), resFolder,
+ IResourceDelta.ADDED);
}
}
}
@@ -578,10 +578,10 @@ public final class ResourceManager {
/**
* Processes a folder and adds it to the list of the project resources.
* @param folder the folder to process
- * @param project the folder's project.
+ * @param resources the resource repository.
* @return the ConfiguredFolder created from this folder, or null if the process failed.
*/
- private ResourceFolder processFolder(IAbstractFolder folder, ProjectResources project) {
+ private ResourceFolder processFolder(IAbstractFolder folder, ResourceRepository resources) {
// split the name of the folder in segments.
String[] folderSegments = folder.getName().split(AndroidConstants.RES_QUALIFIER_SEP);
@@ -593,7 +593,7 @@ public final class ResourceManager {
FolderConfiguration config = getConfig(folderSegments);
if (config != null) {
- ResourceFolder configuredFolder = project.add(type, config, folder);
+ ResourceFolder configuredFolder = resources.add(type, config, folder);
return configuredFolder;
}
@@ -606,37 +606,45 @@ public final class ResourceManager {
* Processes a file and adds it to its parent folder resource.
* @param file the underlying resource file.
* @param folder the parent of the resource file.
+ * @param kind the file change kind.
* @return the {@link ResourceFile} that was created.
*/
- private ResourceFile processFile(IAbstractFile file, ResourceFolder folder) {
+ private ResourceFile processFile(IAbstractFile file, ResourceFolder folder, int kind) {
// get the type of the folder
ResourceFolderType type = folder.getType();
// look for this file if it's already been created
ResourceFile resFile = folder.getFile(file);
- if (resFile != null) {
- // invalidate the file
- resFile.touch();
+ if (resFile == null) {
+ if (kind != IResourceDelta.REMOVED) {
+ // create a ResourceFile for it.
+
+ // check if that's a single or multi resource type folder. For now we define this by
+ // the number of possible resource type output by files in the folder. This does
+ // not make the difference between several resource types from a single file or
+ // the ability to have 2 files in the same folder generating 2 different types of
+ // resource. The former is handled by MultiResourceFile properly while we don't
+ // handle the latter. If we were to add this behavior we'd have to change this call.
+ List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(type);
+
+ if (types.size() == 1) {
+ resFile = new SingleResourceFile(file, folder);
+ } else {
+ resFile = new MultiResourceFile(file, folder);
+ }
+
+ resFile.load();
+
+ // add it to the folder
+ folder.addFile(resFile);
+ }
} else {
- // create a ResourceFile for it.
-
- // check if that's a single or multi resource type folder. For now we define this by
- // the number of possible resource type output by files in the folder. This does
- // not make the difference between several resource types from a single file or
- // the ability to have 2 files in the same folder generating 2 different types of
- // resource. The former is handled by MultiResourceFile properly while we don't
- // handle the latter. If we were to add this behavior we'd have to change this call.
- List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(type);
-
- if (types.size() == 1) {
- resFile = new SingleResourceFile(file, folder);
+ if (kind == IResourceDelta.REMOVED) {
+ folder.removeFile(resFile);
} else {
- resFile = new MultiResourceFile(file, folder);
+ resFile.update();
}
-
- // add it to the folder
- folder.addFile(resFile);
}
return resFile;
@@ -687,4 +695,18 @@ public final class ResourceManager {
defaultConfig.createDefault();
mQualifiers = defaultConfig.getQualifiers();
}
+
+ // debug only
+ @SuppressWarnings("unused")
+ private String getKindString(int kind) {
+ if (DEBUG) {
+ switch (kind) {
+ case IResourceDelta.ADDED: return "ADDED";
+ case IResourceDelta.REMOVED: return "REMOVED";
+ case IResourceDelta.CHANGED: return "CHANGED";
+ }
+ }
+
+ return Integer.toString(kind);
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceRepository.java
new file mode 100644
index 0000000..39de45c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceRepository.java
@@ -0,0 +1,644 @@
+/*
+ * 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.internal.resources.manager;
+
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
+import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier;
+import com.android.ide.eclipse.adt.io.IFolderWrapper;
+import com.android.io.IAbstractFolder;
+import com.android.resources.FolderTypeRelationship;
+import com.android.resources.ResourceFolderType;
+import com.android.resources.ResourceType;
+
+import org.eclipse.core.resources.IFolder;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Base class for resource repository.
+ *
+ * A repository is both a file representation of a resource folder and a representation
+ * of the generated resources, organized by type.
+ *
+ * {@link #getResourceFolder(IFolder)} and {@link #getSourceFiles(ResourceType, String, FolderConfiguration)}
+ * give access to the folders and files of the resource folder.
+ *
+ * {@link #getResources(ResourceType)} gives access to the resources directly.
+ *
+ */
+public abstract class ResourceRepository {
+
+ protected final Map<ResourceFolderType, List<ResourceFolder>> mFolderMap =
+ new EnumMap<ResourceFolderType, List<ResourceFolder>>(ResourceFolderType.class);
+
+ protected final Map<ResourceType, List<ResourceItem>> mResourceMap =
+ new EnumMap<ResourceType, List<ResourceItem>>(ResourceType.class);
+
+ private final Map<List<ResourceItem>, List<ResourceItem>> mReadOnlyListMap =
+ new IdentityHashMap<List<ResourceItem>, List<ResourceItem>>();
+
+ private final boolean mFrameworkRepository;
+
+ protected final IntArrayWrapper mWrapper = new IntArrayWrapper(null);
+
+ /**
+ * Makes a resource repository
+ * @param isFrameworkRepository whether the repository is for framework resources.
+ */
+ protected ResourceRepository(boolean isFrameworkRepository) {
+ mFrameworkRepository = isFrameworkRepository;
+ }
+
+ public boolean isFrameworkRepository() {
+ return mFrameworkRepository;
+ }
+
+ /**
+ * Adds a Folder Configuration to the project.
+ * @param type The resource type.
+ * @param config The resource configuration.
+ * @param folder The workspace folder object.
+ * @return the {@link ResourceFolder} object associated to this folder.
+ */
+ protected ResourceFolder add(ResourceFolderType type, FolderConfiguration config,
+ IAbstractFolder folder) {
+ // get the list for the resource type
+ List<ResourceFolder> list = mFolderMap.get(type);
+
+ if (list == null) {
+ list = new ArrayList<ResourceFolder>();
+
+ ResourceFolder cf = new ResourceFolder(type, config, folder, this);
+ list.add(cf);
+
+ mFolderMap.put(type, list);
+
+ return cf;
+ }
+
+ // look for an already existing folder configuration.
+ for (ResourceFolder cFolder : list) {
+ if (cFolder.mConfiguration.equals(config)) {
+ // config already exist. Nothing to be done really, besides making sure
+ // the IAbstractFolder object is up to date.
+ cFolder.mFolder = folder;
+ return cFolder;
+ }
+ }
+
+ // If we arrive here, this means we didn't find a matching configuration.
+ // So we add one.
+ ResourceFolder cf = new ResourceFolder(type, config, folder, this);
+ list.add(cf);
+
+ return cf;
+ }
+
+ /**
+ * Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}.
+ * @param type The type of the folder
+ * @param removedFolder the IAbstractFolder object.
+ * @return the {@link ResourceFolder} that was removed, or null if no matches were found.
+ */
+ protected ResourceFolder removeFolder(ResourceFolderType type, IAbstractFolder removedFolder) {
+ // get the list of folders for the resource type.
+ List<ResourceFolder> list = mFolderMap.get(type);
+
+ if (list != null) {
+ int count = list.size();
+ for (int i = 0 ; i < count ; i++) {
+ ResourceFolder resFolder = list.get(i);
+ // this is only used for Eclipse stuff so we know it's an IFolderWrapper
+ IAbstractFolder folder = (IFolderWrapper) resFolder.getFolder();
+ if (removedFolder.equals(folder)) {
+ // we found the matching ResourceFolder. we need to remove it.
+ list.remove(i);
+
+ // remove its content
+ resFolder.dispose();
+
+ return resFolder;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a {@link ResourceItem} matching the given {@link ResourceType} and name. If none
+ * exist, it creates one.
+ *
+ * @param type the resource type
+ * @param name the name of the resource.
+ * @return A resource item matching the type and name.
+ */
+ protected ResourceItem getResourceItem(ResourceType type, String name) {
+ // looking for an existing ResourceItem with this type and name
+ ResourceItem item = findDeclaredResourceItem(type, name);
+
+ // create one if there isn't one already, or if the existing one is inlined, since
+ // clearly we need a non inlined one (the inline one is removed too)
+ if (item == null || item.isDeclaredInline()) {
+ ResourceItem oldItem = item != null && item.isDeclaredInline() ? item : null;
+
+ item = createResourceItem(name);
+
+ List<ResourceItem> list = mResourceMap.get(type);
+ if (list == null) {
+ list = new ArrayList<ResourceItem>();
+ mResourceMap.put(type, list);
+ }
+
+ list.add(item);
+
+ if (oldItem != null) {
+ list.remove(oldItem);
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Creates a resource item with the given name.
+ * @param name the name of the resource
+ * @return a new ResourceItem (or child class) instance.
+ */
+ protected abstract ResourceItem createResourceItem(String name);
+
+
+ /**
+ * Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}.
+ * @param type The {@link ResourceFolderType}
+ */
+ public List<ResourceFolder> getFolders(ResourceFolderType type) {
+ return mFolderMap.get(type);
+ }
+
+ public List<ResourceType> getAvailableResourceTypes() {
+ List<ResourceType> list = new ArrayList<ResourceType>();
+
+ // For each key, we check if there's a single ResourceType match.
+ // If not, we look for the actual content to give us the resource type.
+
+ for (ResourceFolderType folderType : mFolderMap.keySet()) {
+ List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(folderType);
+ if (types.size() == 1) {
+ // before we add it we check if it's not already present, since a ResourceType
+ // could be created from multiple folders, even for the folders that only create
+ // one type of resource (drawable for instance, can be created from drawable/ and
+ // values/)
+ if (list.contains(types.get(0)) == false) {
+ list.add(types.get(0));
+ }
+ } else {
+ // there isn't a single resource type out of this folder, so we look for all
+ // content.
+ List<ResourceFolder> folders = mFolderMap.get(folderType);
+ if (folders != null) {
+ for (ResourceFolder folder : folders) {
+ Collection<ResourceType> folderContent = folder.getResourceTypes();
+
+ // then we add them, but only if they aren't already in the list.
+ for (ResourceType folderResType : folderContent) {
+ if (list.contains(folderResType) == false) {
+ list.add(folderResType);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Returns a list of {@link ResourceItem} matching a given {@link ResourceType}.
+ * @param type the type of the resource items to return
+ * @return a non null collection of resource items
+ */
+ public Collection<ResourceItem> getResourceItemsOfType(ResourceType type) {
+ List<ResourceItem> list = mResourceMap.get(type);
+
+ if (list == null) {
+ return Collections.emptyList();
+ }
+
+ List<ResourceItem> roList = mReadOnlyListMap.get(list);
+ if (roList == null) {
+ roList = Collections.unmodifiableList(list);
+ mReadOnlyListMap.put(list, roList);
+ }
+
+ return roList;
+ }
+
+ /**
+ * Returns whether the repository has resources of a given {@link ResourceType}.
+ * @param type the type of resource to check.
+ * @return true if the repository contains resources of the given type, false otherwise.
+ */
+ public boolean hasResourcesOfType(ResourceType type) {
+ List<ResourceItem> items = mResourceMap.get(type);
+ return (items != null && items.size() > 0);
+ }
+
+ /**
+ * Returns the {@link ResourceFolder} associated with a {@link IFolder}.
+ * @param folder The {@link IFolder} object.
+ * @return the {@link ResourceFolder} or null if it was not found.
+ */
+ public ResourceFolder getResourceFolder(IFolder folder) {
+ for (List<ResourceFolder> list : mFolderMap.values()) {
+ for (ResourceFolder resFolder : list) {
+ // this is only used for Eclipse stuff so we know it's an IFolderWrapper
+ IFolderWrapper wrapper = (IFolderWrapper) resFolder.getFolder();
+ if (wrapper.getIFolder().equals(folder)) {
+ return resFolder;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and
+ * configuration.
+ * <p/>This only works with files generating one resource named after the file (for instance,
+ * layouts, bitmap based drawable, xml, anims).
+ * @return the matching file or <code>null</code> if no match was found.
+ */
+ public ResourceFile getMatchingFile(String name, ResourceFolderType type,
+ FolderConfiguration config) {
+ // get the folders for the given type
+ List<ResourceFolder> folders = mFolderMap.get(type);
+
+ // look for folders containing a file with the given name.
+ ArrayList<ResourceFolder> matchingFolders = new ArrayList<ResourceFolder>(folders.size());
+
+ // remove the folders that do not have a file with the given name.
+ for (int i = 0 ; i < folders.size(); i++) {
+ ResourceFolder folder = folders.get(i);
+
+ if (folder.hasFile(name) == true) {
+ matchingFolders.add(folder);
+ }
+ }
+
+ // from those, get the folder with a config matching the given reference configuration.
+ Configurable match = findMatchingConfigurable(matchingFolders, config);
+
+ // do we have a matching folder?
+ if (match instanceof ResourceFolder) {
+ // get the ResourceFile from the filename
+ return ((ResourceFolder)match).getFile(name);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the list of source files for a given resource.
+ * Optionally, if a {@link FolderConfiguration} is given, then only the best
+ * match for this config is returned.
+ *
+ * @param type the type of the resource.
+ * @param name the name of the resource.
+ * @param referenceConfig an optional config for which only the best match will be returned.
+ *
+ * @return a list of files generating this resource or null if it was not found.
+ */
+ public List<ResourceFile> getSourceFiles(ResourceType type, String name,
+ FolderConfiguration referenceConfig) {
+
+ Collection<ResourceItem> items = getResourceItemsOfType(type);
+
+ for (ResourceItem item : items) {
+ if (name.equals(item.getName())) {
+ if (referenceConfig != null) {
+ Configurable match = findMatchingConfigurable(item.getSourceFileList(),
+ referenceConfig);
+ if (match instanceof ResourceFile) {
+ return Collections.singletonList((ResourceFile) match);
+ }
+
+ return null;
+ }
+ return item.getSourceFileList();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the resources values matching a given {@link FolderConfiguration}.
+ *
+ * @param referenceConfig the configuration that each value must match.
+ * @return a map with guaranteed to contain an entry for each {@link ResourceType}
+ */
+ public Map<ResourceType, Map<String, ResourceValue>> getConfiguredResources(
+ FolderConfiguration referenceConfig) {
+ return doGetConfiguredResources(referenceConfig);
+ }
+
+ /**
+ * Returns the resources values matching a given {@link FolderConfiguration} for the current
+ * project.
+ *
+ * @param referenceConfig the configuration that each value must match.
+ * @return a map with guaranteed to contain an entry for each {@link ResourceType}
+ */
+ protected final Map<ResourceType, Map<String, ResourceValue>> doGetConfiguredResources(
+ FolderConfiguration referenceConfig) {
+
+ Map<ResourceType, Map<String, ResourceValue>> map =
+ new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class);
+
+ for (ResourceType key : ResourceType.values()) {
+ // get the local results and put them in the map
+ map.put(key, getConfiguredResource(key, referenceConfig));
+ }
+
+ return map;
+ }
+
+ /**
+ * Returns the sorted list of languages used in the resources.
+ */
+ public SortedSet<String> getLanguages() {
+ SortedSet<String> set = new TreeSet<String>();
+
+ Collection<List<ResourceFolder>> folderList = mFolderMap.values();
+ for (List<ResourceFolder> folderSubList : folderList) {
+ for (ResourceFolder folder : folderSubList) {
+ FolderConfiguration config = folder.getConfiguration();
+ LanguageQualifier lang = config.getLanguageQualifier();
+ if (lang != null) {
+ set.add(lang.getShortDisplayValue());
+ }
+ }
+ }
+
+ return set;
+ }
+
+ /**
+ * Returns the sorted list of regions used in the resources with the given language.
+ * @param currentLanguage the current language the region must be associated with.
+ */
+ public SortedSet<String> getRegions(String currentLanguage) {
+ SortedSet<String> set = new TreeSet<String>();
+
+ Collection<List<ResourceFolder>> folderList = mFolderMap.values();
+ for (List<ResourceFolder> folderSubList : folderList) {
+ for (ResourceFolder folder : folderSubList) {
+ FolderConfiguration config = folder.getConfiguration();
+
+ // get the language
+ LanguageQualifier lang = config.getLanguageQualifier();
+ if (lang != null && lang.getShortDisplayValue().equals(currentLanguage)) {
+ RegionQualifier region = config.getRegionQualifier();
+ if (region != null) {
+ set.add(region.getShortDisplayValue());
+ }
+ }
+ }
+ }
+
+ return set;
+ }
+
+ protected void removeFile(Collection<ResourceType> types, ResourceFile file) {
+ for (ResourceType type : types) {
+ removeFile(type, file);
+ }
+ }
+
+ protected void removeFile(ResourceType type, ResourceFile file) {
+ List<ResourceItem> list = mResourceMap.get(type);
+ for (int i = 0 ; i < list.size(); i++) {
+ ResourceItem item = list.get(i);
+ item.removeFile(file);
+ }
+ }
+
+ /**
+ * Returns a map of (resource name, resource value) for the given {@link ResourceType}.
+ * <p/>The values returned are taken from the resource files best matching a given
+ * {@link FolderConfiguration}.
+ * @param type the type of the resources.
+ * @param referenceConfig the configuration to best match.
+ */
+ private Map<String, ResourceValue> getConfiguredResource(ResourceType type,
+ FolderConfiguration referenceConfig) {
+ // get the resource item for the given type
+ List<ResourceItem> items = mResourceMap.get(type);
+ if (items == null) {
+ return Collections.emptyMap();
+ }
+
+ // create the map
+ HashMap<String, ResourceValue> map = new HashMap<String, ResourceValue>(items.size());
+
+ for (ResourceItem item : items) {
+ // get the source files generating this resource
+ List<ResourceFile> list = item.getSourceFileList();
+
+ // look for the best match for the given configuration
+ Configurable match = findMatchingConfigurable(list, referenceConfig);
+
+ if (match instanceof ResourceFile) {
+ ResourceFile matchResFile = (ResourceFile)match;
+
+ // get the value of this configured resource.
+ ResourceValue value = matchResFile.getValue(type, item.getName());
+
+ if (value != null) {
+ map.put(item.getName(), value);
+ }
+ }
+ }
+
+ return map;
+ }
+
+ /**
+ * Returns the best matching {@link Configurable}.
+ *
+ * @param configurables the list of {@link Configurable} to choose from.
+ * @param referenceConfig the {@link FolderConfiguration} to match.
+ *
+ * @return an item from the given list of {@link Configurable} or null.
+ *
+ * @see http://d.android.com/guide/topics/resources/resources-i18n.html#best-match
+ */
+ private Configurable findMatchingConfigurable(List<? extends Configurable> configurables,
+ FolderConfiguration referenceConfig) {
+ //
+ // 1: eliminate resources that contradict the reference configuration
+ // 2: pick next qualifier type
+ // 3: check if any resources use this qualifier, if no, back to 2, else move on to 4.
+ // 4: eliminate resources that don't use this qualifier.
+ // 5: if more than one resource left, go back to 2.
+ //
+ // The precedence of the qualifiers is more important than the number of qualifiers that
+ // exactly match the device.
+
+ // 1: eliminate resources that contradict
+ ArrayList<Configurable> matchingConfigurables = new ArrayList<Configurable>();
+ for (int i = 0 ; i < configurables.size(); i++) {
+ Configurable res = configurables.get(i);
+
+ if (res.getConfiguration().isMatchFor(referenceConfig)) {
+ matchingConfigurables.add(res);
+ }
+ }
+
+ // if there is only one match, just take it
+ if (matchingConfigurables.size() == 1) {
+ return matchingConfigurables.get(0);
+ } else if (matchingConfigurables.size() == 0) {
+ return null;
+ }
+
+ // 2. Loop on the qualifiers, and eliminate matches
+ final int count = FolderConfiguration.getQualifierCount();
+ for (int q = 0 ; q < count ; q++) {
+ // look to see if one configurable has this qualifier.
+ // At the same time also record the best match value for the qualifier (if applicable).
+
+ // The reference value, to find the best match.
+ // Note that this qualifier could be null. In which case any qualifier found in the
+ // possible match, will all be considered best match.
+ ResourceQualifier referenceQualifier = referenceConfig.getQualifier(q);
+
+ boolean found = false;
+ ResourceQualifier bestMatch = null; // this is to store the best match.
+ for (Configurable configurable : matchingConfigurables) {
+ ResourceQualifier qualifier = configurable.getConfiguration().getQualifier(q);
+ if (qualifier != null) {
+ // set the flag.
+ found = true;
+
+ // Now check for a best match. If the reference qualifier is null ,
+ // any qualifier is a "best" match (we don't need to record all of them.
+ // Instead the non compatible ones are removed below)
+ if (referenceQualifier != null) {
+ if (qualifier.isBetterMatchThan(bestMatch, referenceQualifier)) {
+ bestMatch = qualifier;
+ }
+ }
+ }
+ }
+
+ // 4. If a configurable has a qualifier at the current index, remove all the ones that
+ // do not have one, or whose qualifier value does not equal the best match found above
+ // unless there's no reference qualifier, in which case they are all considered
+ // "best" match.
+ if (found) {
+ for (int i = 0 ; i < matchingConfigurables.size(); ) {
+ Configurable configurable = matchingConfigurables.get(i);
+ ResourceQualifier qualifier = configurable.getConfiguration().getQualifier(q);
+
+ if (qualifier == null) {
+ // this resources has no qualifier of this type: rejected.
+ matchingConfigurables.remove(configurable);
+ } else if (referenceQualifier != null && bestMatch != null &&
+ bestMatch.equals(qualifier) == false) {
+ // there's a reference qualifier and there is a better match for it than
+ // this resource, so we reject it.
+ matchingConfigurables.remove(configurable);
+ } else {
+ // looks like we keep this resource, move on to the next one.
+ i++;
+ }
+ }
+
+ // at this point we may have run out of matching resources before going
+ // through all the qualifiers.
+ if (matchingConfigurables.size() < 2) {
+ break;
+ }
+ }
+ }
+
+ // Because we accept resources whose configuration have qualifiers where the reference
+ // configuration doesn't, we can end up with more than one match. In this case, we just
+ // take the first one.
+ if (matchingConfigurables.size() == 0) {
+ return null;
+ }
+ return matchingConfigurables.get(0);
+ }
+
+ /**
+ * Called after a resource change event, when the resource delta has been processed.
+ */
+ protected void postUpdate() {
+ // Since removed files/folders remove source files from existing ResourceItem, loop through
+ // all resource items and remove the ones that have no source files.
+
+ Collection<List<ResourceItem>> lists = mResourceMap.values();
+ for (List<ResourceItem> list : lists) {
+ for (int i = 0 ; i < list.size() ;) {
+ if (list.get(i).hasNoSourceFile()) {
+ list.remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Looks up an existing {@link ResourceItem} by {@link ResourceType} and name. This
+ * ignores inline resources.
+ * @param type the Resource Type.
+ * @param name the Resource name.
+ * @return the existing ResourceItem or null if no match was found.
+ */
+ private ResourceItem findDeclaredResourceItem(ResourceType type, String name) {
+ List<ResourceItem> list = mResourceMap.get(type);
+
+ if (list != null) {
+ for (ResourceItem item : list) {
+ // ignore inline
+ if (name.equals(item.getName()) && item.isDeclaredInline() == false) {
+ return item;
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java
index 8677e5d..bb8feb0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java
@@ -23,7 +23,6 @@ import com.android.io.IAbstractFile;
import com.android.resources.FolderTypeRelationship;
import com.android.resources.ResourceType;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -74,33 +73,37 @@ public class SingleResourceFile extends ResourceFile {
}
@Override
- public List<ResourceType> getResourceTypes() {
- return FolderTypeRelationship.getRelatedResourceTypes(getFolder().getType());
+ protected void load() {
+ // get a resource item matching the given type and name
+ ResourceItem item = getRepository().getResourceItem(mType, mResourceName);
+
+ // add this file to the list of files generating this resource item.
+ item.add(this);
}
@Override
- public boolean hasResources(ResourceType type) {
- return FolderTypeRelationship.match(type, getFolder().getType());
+ protected void update() {
+ // when this happens, nothing needs to be done since the file only generates
+ // a single resources that doesn't actually change (its content is the file path)
}
@Override
- public Collection<ProjectResourceItem> getResources(ResourceType type,
- ProjectResources projectResources) {
-
- // looking for an existing ResourceItem with this name and type
- ProjectResourceItem item = projectResources.findResourceItem(type, mResourceName);
+ protected void dispose() {
+ // only remove this file from the existing ResourceItem.
+ getFolder().getRepository().removeFile(mType, this);
- ArrayList<ProjectResourceItem> items = new ArrayList<ProjectResourceItem>();
-
- if (item == null) {
- item = new ConfigurableResourceItem(mResourceName);
- items.add(item);
- }
+ // don't need to touch the content, it'll get reclaimed as this objects disappear.
+ // In the mean time other objects may need to access it.
+ }
- // add this ResourceFile to the ResourceItem
- item.add(this);
+ @Override
+ public Collection<ResourceType> getResourceTypes() {
+ return FolderTypeRelationship.getRelatedResourceTypes(getFolder().getType());
+ }
- return items;
+ @Override
+ public boolean hasResources(ResourceType type) {
+ return FolderTypeRelationship.match(type, getFolder().getType());
}
/*
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
index ccf4301..62aa180 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
@@ -16,12 +16,6 @@
package com.android.ide.eclipse.adt.internal.sdk;
-import static com.android.AndroidConstants.FD_RES_VALUES;
-import static com.android.sdklib.SdkConstants.FD_DATA;
-import static com.android.sdklib.SdkConstants.FD_RES;
-
-import static java.io.File.separator;
-
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.sdk.LoadStatus;
@@ -32,35 +26,18 @@ import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.Android
import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.adt.internal.editors.xml.descriptors.XmlDescriptors;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.resources.ResourceType;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import org.eclipse.core.runtime.IStatus;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
/**
* This class contains the data of an Android Target as loaded from the SDK.
*/
@@ -89,17 +66,14 @@ public class AndroidTargetData {
*/
private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
- private IResourceRepository mSystemResourceRepository;
-
private AndroidManifestDescriptors mManifestDescriptors;
private LayoutDescriptors mLayoutDescriptors;
private MenuDescriptors mMenuDescriptors;
private XmlDescriptors mXmlDescriptors;
private Map<String, Map<String, Integer>> mEnumValueMap;
- private Map<ResourceType, Collection<String>> mPublicAttributeNames;
- private ProjectResources mFrameworkResources;
+ private ResourceRepository mFrameworkResources;
private LayoutLibrary mLayoutLibrary;
private boolean mLayoutBridgeInit = false;
@@ -113,7 +87,7 @@ public class AndroidTargetData {
* @param platformLibraries
* @param optionalLibraries
*/
- void setExtraData(IResourceRepository systemResourceRepository,
+ void setExtraData(
AndroidManifestDescriptors manifestDescriptors,
LayoutDescriptors layoutDescriptors,
MenuDescriptors menuDescriptors,
@@ -126,16 +100,15 @@ public class AndroidTargetData {
String[] intentCategoryValues,
String[] platformLibraries,
IOptionalLibrary[] optionalLibraries,
- ProjectResources resources,
+ ResourceRepository frameworkResources,
LayoutLibrary layoutLibrary) {
- mSystemResourceRepository = systemResourceRepository;
mManifestDescriptors = manifestDescriptors;
mLayoutDescriptors = layoutDescriptors;
mMenuDescriptors = menuDescriptors;
mXmlDescriptors = xmlDescriptors;
mEnumValueMap = enumValueMap;
- mFrameworkResources = resources;
+ mFrameworkResources = frameworkResources;
mLayoutLibrary = layoutLibrary;
setPermissions(permissionValues);
@@ -144,10 +117,6 @@ public class AndroidTargetData {
setOptionalLibraries(platformLibraries, optionalLibraries);
}
- 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},
@@ -263,7 +232,7 @@ public class AndroidTargetData {
/**
* Returns the {@link ProjectResources} containing the Framework Resources.
*/
- public ProjectResources getFrameworkResources() {
+ public ResourceRepository getFrameworkResources() {
return mFrameworkResources;
}
@@ -360,124 +329,4 @@ public class AndroidTargetData {
mAttributeValues.remove(name);
mAttributeValues.put(name, values);
}
-
- /**
- * Returns true if the given name represents a public attribute of the given type.
- *
- * @param type the type of resource
- * @param name the name of the resource
- * @return true if the given property is public
- */
- public boolean isPublicResource(ResourceType type, String name) {
- Collection<String> names = getNameMap(type);
- if (names != null) {
- return names.contains(name);
- }
-
- return false;
- }
-
- /**
- * Returns all public properties (in no particular order) of a given resource type.
- *
- * @param type the type of resource
- * @return an unmodifiable collection of public resource names
- */
- public Collection<String> getPublicResourceNames(ResourceType type) {
- Collection<String> names = getNameMap(type);
- if (names != null) {
- return Collections.<String>unmodifiableCollection(names);
- }
-
- return Collections.emptyList();
- }
-
- /** Returns a (possibly cached) list of names for the given resource type, or null */
- private Collection<String> getNameMap(ResourceType type) {
- if (mPublicAttributeNames == null) {
- mPublicAttributeNames = readPublicAttributeLists();
- }
-
- return mPublicAttributeNames.get(type);
- }
-
- /**
- * Reads the public.xml file in data/res/values/ for this SDK and
- * returns the result as a map from resource type to a list of names
- */
- private Map<ResourceType, Collection<String>> readPublicAttributeLists() {
- String relative = FD_DATA + separator + FD_RES + separator + FD_RES_VALUES + separator +
- "public.xml"; //$NON-NLS-1$
- File file = new File(mTarget.getLocation(), relative);
- if (file.isFile()) {
- Map<ResourceType, Collection<String>> map =
- new HashMap<ResourceType, Collection<String>>();
- Document document = null;
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- Reader reader = null;
- try {
- reader = new BufferedReader(new FileReader(file));
- InputSource is = new InputSource(reader);
- factory.setNamespaceAware(true);
- factory.setValidating(false);
- DocumentBuilder builder = factory.newDocumentBuilder();
- document = builder.parse(is);
-
- ResourceType lastType = null;
- String lastTypeName = "";
-
- NodeList children = document.getDocumentElement().getChildNodes();
- for (int i = 0, n = children.getLength(); i < n; i++) {
- Node node = children.item(i);
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- Element element = (Element) node;
- String name = element.getAttribute("name"); //$NON-NLS-1$
- if (name.length() > 0) {
- String typeName = element.getAttribute("type"); //$NON-NLS-1$
- ResourceType type = null;
- if (typeName.equals(lastTypeName)) {
- type = lastType;
- } else {
- type = ResourceType.getEnum(typeName);
- lastType = type;
- lastTypeName = typeName;
- }
- if (type != null) {
- Collection<String> list = map.get(type);
- if (list == null) {
- // Use sets for some of the larger maps to make
- // searching for isPublicResource faster.
- if (type == ResourceType.ATTR) {
- list = new HashSet<String>(900);
- } else if (type == ResourceType.STYLE) {
- list = new HashSet<String>(300);
- } else if (type == ResourceType.DRAWABLE) {
- list = new HashSet<String>(200);
- } else {
- list = new ArrayList<String>(30);
- }
- map.put(type, list);
- }
- list.add(name);
- }
- }
- }
- }
- } catch (Exception e) {
- AdtPlugin.log(e, "Can't read and parse public attribute list");
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // Nothing to be done here - we don't care if it closed or not.
- }
- }
- }
-
- return map;
-
- }
- return Collections.emptyMap();
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
index 6426fdb..977c759 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java
@@ -25,11 +25,8 @@ import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDes
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.adt.internal.editors.xml.descriptors.XmlDescriptors;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.resources.ResourceType;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
@@ -86,7 +83,7 @@ public final class AndroidTargetParser {
try {
SubMonitor progress = SubMonitor.convert(monitor,
String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
- 13);
+ 12);
AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget);
@@ -101,15 +98,6 @@ public final class AndroidTargetParser {
return Status.CANCEL_STATUS;
}
- // get the resource Ids.
- progress.subTask("Resource IDs");
- IResourceRepository frameworkRepository = collectResourceIds(classLoader);
- progress.worked(1);
-
- if (progress.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
-
// get the permissions
progress.subTask("Permissions");
String[] permissionValues = collectPermissions(classLoader);
@@ -231,8 +219,8 @@ public final class AndroidTargetParser {
progress.worked(1);
// load the framework resources.
- ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
- mAndroidTarget);
+ ResourceRepository frameworkResources =
+ ResourceManager.getInstance().loadFrameworkResources(mAndroidTarget);
progress.worked(1);
// now load the layout lib bridge
@@ -243,7 +231,7 @@ public final class AndroidTargetParser {
progress.worked(1);
// and finally create the PlatformData with all that we loaded.
- targetData.setExtraData(frameworkRepository,
+ targetData.setExtraData(
manifestDescriptors,
layoutDescriptors,
menuDescriptors,
@@ -256,7 +244,7 @@ public final class AndroidTargetParser {
categories.toArray(new String[categories.size()]),
mAndroidTarget.getPlatformLibraries(),
mAndroidTarget.getOptionalLibraries(),
- resources,
+ frameworkResources,
layoutBridge);
Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
@@ -290,72 +278,6 @@ public final class AndroidTargetParser {
}
/**
- * 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 IResourceRepository collectResourceIds(
- AndroidJarLoader classLoader) {
- try {
- Class<?> r = classLoader.loadClass(SdkConstants.CLASS_R);
-
- if (r != null) {
- 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$
- SdkConstants.CLASS_R,
- mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
- }
-
- return null;
- }
-
- /**
- * Parse the R class and build the resource map.
- *
- * @param rClass the Class object representing the Resources.
- * @return a map of the resource or null
- */
- private Map<ResourceType, List<ResourceItem>> parseRClass(Class<?> rClass) {
- // get the sub classes.
- Class<?>[] classes = rClass.getClasses();
-
- if (classes.length > 0) {
- HashMap<ResourceType, List<ResourceItem>> map =
- new HashMap<ResourceType, List<ResourceItem>>();
-
- // get the fields of each class.
- for (int c = 0 ; c < classes.length ; c++) {
- Class<?> subClass = classes[c];
- String name = subClass.getSimpleName();
-
- // get the matching ResourceType
- ResourceType type = ResourceType.getEnum(name);
- if (type != null) {
- List<ResourceItem> list = new ArrayList<ResourceItem>();
- map.put(type, list);
-
- Field[] fields = subClass.getFields();
-
- for (Field f : fields) {
- list.add(new ResourceItem(f.getName()));
- }
- }
- }
-
- return map;
- }
-
- return null;
- }
-
- /**
* Loads, collects and returns the list of default permissions from the framework.
*
* @param classLoader The framework SDK jar classloader
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/FrameworkResourceRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/FrameworkResourceRepository.java
deleted file mode 100644
index 247a888..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/FrameworkResourceRepository.java
+++ /dev/null
@@ -1,76 +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.internal.sdk;
-
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
-import com.android.resources.ResourceType;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Implementation of the {@link IResourceRepository} interface to hold the system resource Ids
- * parsed by {@link AndroidTargetParser}.
- */
-final class FrameworkResourceRepository implements IResourceRepository {
-
- private Map<ResourceType, List<ResourceItem>> mResourcesMap;
-
- public FrameworkResourceRepository(Map<ResourceType, List<ResourceItem>> systemResourcesMap) {
- mResourcesMap = systemResourcesMap;
- }
-
- public ResourceType[] getAvailableResourceTypes() {
- if (mResourcesMap != null) {
- Set<ResourceType> types = mResourcesMap.keySet();
-
- if (types != null) {
- return types.toArray(new ResourceType[types.size()]);
- }
- }
-
- return null;
- }
-
- public ResourceItem[] getResources(ResourceType type) {
- if (mResourcesMap != null) {
- List<ResourceItem> items = mResourcesMap.get(type);
-
- if (items != null) {
- return items.toArray(new ResourceItem[items.size()]);
- }
- }
-
- return null;
- }
-
- public boolean hasResources(ResourceType type) {
- if (mResourcesMap != null) {
- List<ResourceItem> items = mResourcesMap.get(type);
-
- return (items != null && items.size() > 0);
- }
-
- return false;
- }
-
- public boolean isSystemRepository() {
- return true;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/MarginChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/MarginChooser.java
index 1a9a78f..3c291f3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/MarginChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/MarginChooser.java
@@ -15,8 +15,9 @@
*/
package com.android.ide.eclipse.adt.internal.ui;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
+import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.resources.ResourceType;
@@ -196,11 +197,11 @@ public class MarginChooser extends SelectionStatusDialog implements Listener {
Button button = (Button) event.widget;
// Open a resource chooser dialog for specified resource type.
- IResourceRepository projectRepository = ResourceManager.getInstance()
+ ProjectResources projectRepository = ResourceManager.getInstance()
.getProjectResources(mProject);
- IResourceRepository systemRepository = mTargetData.getSystemResources();
+ ResourceRepository frameworkRepository = mTargetData.getFrameworkResources();
ResourceChooser dlg = new ResourceChooser(mProject, ResourceType.DIMEN,
- projectRepository, systemRepository, getShell());
+ projectRepository, frameworkRepository, getShell());
Text text = (Text) button.getData(PROP_TEXTFIELD);
dlg.setCurrentResource(text.getText().trim());
if (dlg.open() == Window.OK) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
index 2a170a4..c6bbd0d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
@@ -19,9 +19,9 @@ package com.android.ide.eclipse.adt.internal.ui;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.resources.ResourceType;
import org.eclipse.core.resources.IProject;
@@ -52,6 +52,7 @@ import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
+import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -66,7 +67,7 @@ public class ReferenceChooserDialog extends SelectionStatusDialog {
private static IDialogSettings sDialogSettings = new DialogSettings("");
- private IResourceRepository mResources;
+ private ResourceRepository mProjectResources;
private String mCurrentResource;
private FilteredTree mFilteredTree;
private Button mNewResButton;
@@ -77,10 +78,11 @@ public class ReferenceChooserDialog extends SelectionStatusDialog {
* @param project
* @param parent
*/
- public ReferenceChooserDialog(IProject project, IResourceRepository resources, Shell parent) {
+ public ReferenceChooserDialog(IProject project, ResourceRepository projectResources,
+ Shell parent) {
super(parent);
mProject = project;
- mResources = resources;
+ mProjectResources = projectResources;
int shellStyle = getShellStyle();
setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
@@ -177,7 +179,7 @@ public class ReferenceChooserDialog extends SelectionStatusDialog {
mTreeViewer.setLabelProvider(new ResourceLabelProvider());
mTreeViewer.setContentProvider(new ResourceContentProvider(false /* fullLevels */));
- mTreeViewer.setInput(mResources);
+ mTreeViewer.setInput(mProjectResources);
}
protected void handleSelection() {
@@ -339,7 +341,8 @@ public class ReferenceChooserDialog extends SelectionStatusDialog {
*/
private void setupInitialSelection(ResourceType resourceType, String resourceName) {
// get all the resources of this type
- ResourceItem[] resourceItems = mResources.getResources(resourceType);
+ Collection<ResourceItem> resourceItems =
+ mProjectResources.getResourceItemsOfType(resourceType);
for (ResourceItem resourceItem : resourceItems) {
if (resourceName.equals(resourceItem.getName())) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
index 87d1b75..b57de72 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
@@ -28,12 +28,10 @@ import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.Resour
import com.android.ide.eclipse.adt.internal.editors.xml.Hyperlinks;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.resources.ResourceType;
import org.eclipse.core.resources.IFile;
@@ -77,10 +75,8 @@ import org.w3c.dom.Text;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -92,7 +88,8 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
private Pattern mProjectResourcePattern;
private ResourceType mResourceType;
- private IResourceRepository mProjectResources;
+ private final ResourceRepository mProjectResources;
+ private final ResourceRepository mFrameworkResources;
private Pattern mSystemResourcePattern;
private Button mProjectButton;
private Button mSystemButton;
@@ -105,18 +102,19 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
* @param project Project being worked on
* @param type The type of the resource to choose
* @param projectResources The repository for the project
- * @param systemResources The System resource repository
+ * @param frameworkResources The Framework resource repository
* @param parent the parent shell
*/
public ResourceChooser(IProject project, ResourceType type,
- IResourceRepository projectResources,
- IResourceRepository systemResources,
+ ResourceRepository projectResources,
+ ResourceRepository frameworkResources,
Shell parent) {
super(parent, new ResourceLabelProvider());
mProject = project;
mResourceType = type;
mProjectResources = projectResources;
+ mFrameworkResources = frameworkResources;
mProjectResourcePattern = Pattern.compile(
"@" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -371,25 +369,21 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
* Setups the current list.
*/
private ResourceItem[] setupResourceList() {
- ResourceItem[] items = null;
+ Collection<ResourceItem> items = null;
if (mProjectButton.getSelection()) {
- items = mProjectResources.getResources(mResourceType);
- setListElements(items);
+ items = mProjectResources.getResourceItemsOfType(mResourceType);
} else if (mSystemButton.getSelection()) {
- AndroidTargetData targetData = Sdk.getCurrent().getTargetData(mProject);
- if (targetData != null) {
- Collection<String> names = targetData.getPublicResourceNames(mResourceType);
- List<ResourceItem> list = new ArrayList<ResourceItem>();
- for (String name : names) {
- list.add(new ResourceItem(name));
- }
- Collections.sort(list);
- items = list.toArray(new ResourceItem[list.size()]);
- setListElements(items);
- }
+ items = mFrameworkResources.getResourceItemsOfType(mResourceType);
}
- return items;
+ ResourceItem[] arrayItems = items.toArray(new ResourceItem[items.size()]);
+
+ // sort the array
+ Arrays.sort(arrayItems);
+
+ setListElements(arrayItems);
+
+ return arrayItems;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceContentProvider.java
index f57b74e..ee13416 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceContentProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceContentProvider.java
@@ -16,15 +16,18 @@
package com.android.ide.eclipse.adt.internal.ui;
-import com.android.ide.eclipse.adt.internal.resources.IResourceRepository;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.manager.ConfigurableResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.resources.ResourceType;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
/**
* Content provider for the Resource Explorer TreeView.
* Each level of the tree is represented by a different class.
@@ -40,10 +43,10 @@ import org.eclipse.jface.viewers.Viewer;
* <li>{@link ResourceFile}. (optional) This represents a particular version of the
* {@link ResourceItem}. It is displayed as a list of resource qualifier.
* </li>
- * </ul>
- * </ul>
- * </ul>
- *
+ * </ul>
+ * </ul>
+ * </ul>
+ *
* @see ResourceLabelProvider
*/
public class ResourceContentProvider implements ITreeContentProvider {
@@ -51,10 +54,10 @@ public class ResourceContentProvider implements ITreeContentProvider {
/**
* The current ProjectResources being displayed.
*/
- private IResourceRepository mResources;
-
+ private ResourceRepository mResources;
+
private boolean mFullLevels;
-
+
/**
* Constructs a new content providers for resource display.
* @param fullLevels if <code>true</code> the content provider will suppport all 3 levels. If
@@ -66,9 +69,12 @@ public class ResourceContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof ResourceType) {
- return mResources.getResources((ResourceType)parentElement);
- } else if (mFullLevels && parentElement instanceof ConfigurableResourceItem) {
- return ((ConfigurableResourceItem)parentElement).getSourceFileArray();
+ Object[] array = mResources.getResourceItemsOfType(
+ (ResourceType)parentElement).toArray();
+ Arrays.sort(array);
+ return array;
+ } else if (mFullLevels && parentElement instanceof ResourceItem) {
+ return ((ResourceItem)parentElement).getSourceFileArray();
}
return null;
}
@@ -80,18 +86,20 @@ public class ResourceContentProvider implements ITreeContentProvider {
public boolean hasChildren(Object element) {
if (element instanceof ResourceType) {
- return mResources.hasResources((ResourceType)element);
- } else if (mFullLevels && element instanceof ConfigurableResourceItem) {
- return ((ConfigurableResourceItem)element).hasAlternates();
+ return mResources.hasResourcesOfType((ResourceType)element);
+ } else if (mFullLevels && element instanceof ResourceItem) {
+ return ((ResourceItem)element).hasAlternates();
}
return false;
}
public Object[] getElements(Object inputElement) {
- if (inputElement instanceof IResourceRepository) {
- if ((IResourceRepository)inputElement == mResources) {
+ if (inputElement instanceof ResourceRepository) {
+ if ((ResourceRepository)inputElement == mResources) {
// get the top level resources.
- return mResources.getAvailableResourceTypes();
+ List<ResourceType> types = mResources.getAvailableResourceTypes();
+ Collections.sort(types);
+ return types.toArray();
}
}
@@ -103,8 +111,8 @@ public class ResourceContentProvider implements ITreeContentProvider {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- if (newInput instanceof IResourceRepository) {
- mResources = (IResourceRepository)newInput;
+ if (newInput instanceof ResourceRepository) {
+ mResources = (ResourceRepository)newInput;
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceExplorerView.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceExplorerView.java
index 081b6b6..6115215 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceExplorerView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceExplorerView.java
@@ -18,7 +18,7 @@ package com.android.ide.eclipse.adt.internal.ui;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
@@ -138,10 +138,10 @@ public class ResourceExplorerView extends ViewPart implements ISelectionListener
}
} catch (PartInitException e) {
}
- } else if (element instanceof ProjectResourceItem) {
+ } else if (element instanceof ResourceItem) {
// if it's a ResourceItem, we open the first file, but only if
// there's no alternate files.
- ProjectResourceItem item = (ProjectResourceItem)element;
+ ResourceItem item = (ResourceItem)element;
if (item.isEditableDirectly()) {
ResourceFile[] files = item.getSourceFileArray();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceLabelProvider.java
index 50e1d07..f08389f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceLabelProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceLabelProvider.java
@@ -16,10 +16,7 @@
package com.android.ide.eclipse.adt.internal.ui;
-import com.android.ide.eclipse.adt.internal.resources.IIdResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.ResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.manager.ConfigurableResourceItem;
-import com.android.ide.eclipse.adt.internal.resources.manager.IdResourceItem;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile;
import com.android.resources.ResourceType;
@@ -47,15 +44,15 @@ import org.eclipse.ui.PlatformUI;
* <li>{@link ResourceFile}. This represents a particular version of the {@link ResourceItem}.
* It is displayed as a list of resource qualifier.
* </li>
- * </ul>
- * </ul>
- * </ul>
- *
+ * </ul>
+ * </ul>
+ * </ul>
+ *
* @see ResourceContentProvider
*/
public class ResourceLabelProvider implements ILabelProvider, ITableLabelProvider {
private Image mWarningImage;
-
+
public ResourceLabelProvider() {
mWarningImage = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
ISharedImages.IMG_OBJS_WARN_TSK).createImage();
@@ -94,8 +91,8 @@ public class ResourceLabelProvider implements ILabelProvider, ITableLabelProvide
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 1) {
- if (element instanceof ConfigurableResourceItem) {
- ConfigurableResourceItem item = (ConfigurableResourceItem)element;
+ if (element instanceof ResourceItem) {
+ ResourceItem item = (ResourceItem)element;
if (item.hasDefault() == false) {
return mWarningImage;
}
@@ -116,19 +113,18 @@ public class ResourceLabelProvider implements ILabelProvider, ITableLabelProvide
}
break;
case 1:
- if (element instanceof ConfigurableResourceItem) {
- ConfigurableResourceItem item = (ConfigurableResourceItem)element;
- int count = item.getAlternateCount();
- if (count > 0) {
- if (item.hasDefault()) {
- count++;
- }
- return String.format("%1$d version(s)", count);
- }
- } else if (element instanceof IIdResourceItem) {
- IIdResourceItem idResource = (IIdResourceItem)element;
- if (idResource.isDeclaredInline()) {
+ if (element instanceof ResourceItem) {
+ ResourceItem item = (ResourceItem)element;
+ if (item.isDeclaredInline()) {
return "Declared inline";
+ } else {
+ int count = item.getAlternateCount();
+ if (count > 0) {
+ if (item.hasDefault()) {
+ count++;
+ }
+ return String.format("%1$d version(s)", count);
+ }
}
}
return null;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java
index 5131126..7fcb333 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java
@@ -38,6 +38,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMe
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceRepository;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.tests.SdkTestCase;
import com.android.io.FolderWrapper;
@@ -175,7 +176,7 @@ public class ApiDemosRenderingTest extends SdkTestCase {
}
// first load the project's target framework resource
- ProjectResources framework = ResourceManager.getInstance().loadFrameworkResources(target);
+ ResourceRepository framework = ResourceManager.getInstance().loadFrameworkResources(target);
// now load the project resources
ProjectResources project = new ProjectResources(null /*project*/);
diff --git a/ide_common/src/com/android/ide/common/resources/ResourceResolver.java b/ide_common/src/com/android/ide/common/resources/ResourceResolver.java
index 2a06373..9493c35 100644
--- a/ide_common/src/com/android/ide/common/resources/ResourceResolver.java
+++ b/ide_common/src/com/android/ide/common/resources/ResourceResolver.java
@@ -121,14 +121,10 @@ public class ResourceResolver extends RenderResources {
if (frameworkTheme) {
Map<String, ResourceValue> frameworkStyleMap = mFrameworkResources.get(
ResourceType.STYLE);
- if (frameworkStyleMap != null) {
- theme = frameworkStyleMap.get(name);
- }
+ theme = frameworkStyleMap.get(name);
} else {
Map<String, ResourceValue> projectStyleMap = mProjectResources.get(ResourceType.STYLE);
- if (projectStyleMap != null) {
- theme = projectStyleMap.get(name);
- }
+ theme = projectStyleMap.get(name);
}
if (theme instanceof StyleResourceValue) {
@@ -334,29 +330,25 @@ public class ResourceResolver extends RenderResources {
// if allowed, search in the project resources first.
if (frameworkOnly == false) {
typeMap = mProjectResources.get(resType);
- if (typeMap != null) {
- ResourceValue item = typeMap.get(resName);
- if (item != null) {
- return item;
- }
+ ResourceValue item = typeMap.get(resName);
+ if (item != null) {
+ return item;
}
}
// now search in the framework resources.
typeMap = mFrameworkResources.get(resType);
- if (typeMap != null) {
- ResourceValue item = typeMap.get(resName);
- if (item != null) {
- return item;
- }
+ ResourceValue item = typeMap.get(resName);
+ if (item != null) {
+ return item;
+ }
- // if it was not found and the type is an id, it is possible that the ID was
- // generated dynamically when compiling the framework resources.
- // Look for it in the R map.
- if (mFrameworkProvider != null && resType == ResourceType.ID) {
- if (mFrameworkProvider.getId(resType, resName) != null) {
- return new ResourceValue(resType, resName, true);
- }
+ // if it was not found and the type is an id, it is possible that the ID was
+ // generated dynamically when compiling the framework resources.
+ // Look for it in the R map.
+ if (mFrameworkProvider != null && resType == ResourceType.ID) {
+ if (mFrameworkProvider.getId(resType, resName) != null) {
+ return new ResourceValue(resType, resName, true);
}
}
@@ -397,32 +389,30 @@ public class ResourceResolver extends RenderResources {
Map<String, ResourceValue> projectStyleMap = mProjectResources.get(ResourceType.STYLE);
Map<String, ResourceValue> frameworkStyleMap = mFrameworkResources.get(ResourceType.STYLE);
- if (projectStyleMap != null && frameworkStyleMap != null) {
- // first, get the theme
- ResourceValue theme = null;
-
- // project theme names have been prepended with a *
- if (isProjectTheme) {
- theme = projectStyleMap.get(themeName);
- } else {
- theme = frameworkStyleMap.get(themeName);
- }
-
- if (theme instanceof StyleResourceValue) {
- // compute the inheritance map for both the project and framework styles
- computeStyleInheritance(projectStyleMap.values(), projectStyleMap,
- frameworkStyleMap);
+ // first, get the theme
+ ResourceValue theme = null;
- // Compute the style inheritance for the framework styles/themes.
- // Since, for those, the style parent values do not contain 'android:'
- // we want to force looking in the framework style only to avoid using
- // similarly named styles from the project.
- // To do this, we pass null in lieu of the project style map.
- computeStyleInheritance(frameworkStyleMap.values(), null /*inProjectStyleMap */,
- frameworkStyleMap);
+ // project theme names have been prepended with a *
+ if (isProjectTheme) {
+ theme = projectStyleMap.get(themeName);
+ } else {
+ theme = frameworkStyleMap.get(themeName);
+ }
- mTheme = (StyleResourceValue) theme;
- }
+ if (theme instanceof StyleResourceValue) {
+ // compute the inheritance map for both the project and framework styles
+ computeStyleInheritance(projectStyleMap.values(), projectStyleMap,
+ frameworkStyleMap);
+
+ // Compute the style inheritance for the framework styles/themes.
+ // Since, for those, the style parent values do not contain 'android:'
+ // we want to force looking in the framework style only to avoid using
+ // similarly named styles from the project.
+ // To do this, we pass null in lieu of the project style map.
+ computeStyleInheritance(frameworkStyleMap.values(), null /*inProjectStyleMap */,
+ frameworkStyleMap);
+
+ mTheme = (StyleResourceValue) theme;
}
}