aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2011-01-14 17:13:26 -0800
committerAndroid Code Review <code-review@android.com>2011-01-14 17:13:26 -0800
commit36e3d648bdada3818fc10a0753a2c6fb468d41ca (patch)
tree17230bd4ada6dcf2aae752a6bab1c61449a4f1fd
parent1ed748ab4fdcf2662c59cfd61ef5dad3a4cce0a2 (diff)
parentdcef17367f317f2b79dca6069a46bedc06ffd4e9 (diff)
downloadsdk-36e3d648bdada3818fc10a0753a2c6fb468d41ca.zip
sdk-36e3d648bdada3818fc10a0753a2c6fb468d41ca.tar.gz
sdk-36e3d648bdada3818fc10a0753a2c6fb468d41ca.tar.bz2
Merge "Improve hyperlink resolution for configurations" into tools_r9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java11
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java365
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFileWrapper.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFolderWrapper.java5
4 files changed, 258 insertions, 128 deletions
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 9090baf..73ad04a 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
@@ -1409,7 +1409,7 @@ public class GraphicalEditorPart extends EditorPart
* target set.
*
*/
- private IAndroidTarget getRenderingTarget() {
+ public IAndroidTarget getRenderingTarget() {
// if the SDK is null no targets are loaded.
Sdk currentSdk = Sdk.getCurrent();
if (currentSdk == null) {
@@ -2323,4 +2323,13 @@ public class GraphicalEditorPart extends EditorPart
return Collections.emptyList();
}
}
+
+ /**
+ * Return this editor's current configuration
+ *
+ * @return the current configuration
+ */
+ public FolderConfiguration getConfiguration() {
+ return mConfigComposite.getCurrentConfig();
+ }
}
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 a2e664b..f593619 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
@@ -24,10 +24,9 @@ import static com.android.ide.eclipse.adt.AndroidConstants.ANDROID_PKG;
import static com.android.ide.eclipse.adt.AndroidConstants.EXT_XML;
import static com.android.ide.eclipse.adt.AndroidConstants.FN_RESOURCE_BASE;
import static com.android.ide.eclipse.adt.AndroidConstants.FN_RESOURCE_CLASS;
-import static com.android.ide.eclipse.adt.AndroidConstants.WS_RESOURCES;
-import static com.android.ide.eclipse.adt.AndroidConstants.WS_SEP;
import static com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors.NAME_ATTR;
import static com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors.ROOT_ELEMENT;
+import static com.android.sdklib.SdkConstants.FD_VALUES;
import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_NAME;
import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_PACKAGE;
import static com.android.sdklib.xml.AndroidManifest.NODE_ACTIVITY;
@@ -37,19 +36,23 @@ import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
+import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
import com.android.ide.eclipse.adt.internal.resources.ResourceType;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.adt.internal.resources.manager.FolderTypeRelationship;
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.ResourceFolderType;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
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.IFolderWrapper;
+import com.android.ide.eclipse.adt.io.IFileWrapper;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.annotations.VisibleForTesting;
+import com.android.sdklib.io.FileWrapper;
import com.android.sdklib.util.Pair;
import org.apache.xerces.parsers.DOMParser;
@@ -98,6 +101,7 @@ import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.wst.sse.core.StructuredModelManager;
@@ -122,6 +126,7 @@ import org.xml.sax.SAXException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -230,6 +235,10 @@ public class Hyperlinks {
/** Returns true if this represents a {@code <foo.bar.Baz>} custom view class element */
private static boolean isClassElement(XmlContext context) {
+ if (context.getAttribute() != null) {
+ // Don't match the outer element if the user is hovering over a specific attribute
+ return false;
+ }
// If the element looks like a fully qualified class name (e.g. it's a custom view
// element) offer it as a link
String tag = context.getElement().getTagName();
@@ -479,7 +488,6 @@ public class Hyperlinks {
status.setErrorMessage(message);
}
-
/**
* Opens a framework resource's declaration
*
@@ -494,25 +502,15 @@ public class Hyperlinks {
return false;
}
- Sdk currentSdk = Sdk.getCurrent();
- if (currentSdk == null) {
- return false;
- }
- IAndroidTarget target = currentSdk.getTarget(project);
- if (target == null) {
- return false;
- }
ResourceType type = parsedUrl.getFirst();
String name = parsedUrl.getSecond();
// Attempt to open files, such as layouts and drawables in @android?
if (isFileResource(type)) {
- AndroidTargetData data = currentSdk.getTargetData(target);
- if (data == null) {
+ ProjectResources frameworkResources = getResources(project, true /* framework */);
+ if (frameworkResources == null) {
return false;
}
-
- ProjectResources frameworkResources = data.getFrameworkResources();
Map<String, Map<String, ResourceValue>> configuredResources =
frameworkResources.getConfiguredResources(new FolderConfiguration());
@@ -560,22 +558,93 @@ public class Hyperlinks {
break;
}
}
- } else if (isValueResource(type)) {
- File values = new File(target.getPath(IAndroidTarget.RESOURCES),
- SdkConstants.FD_VALUES);
- if (values.exists()) {
- Pair<File, Integer> match = findValueDefinition(values, type, name);
- if (match != null) {
- Path path = new Path(match.getFirst().getPath());
- openPath(path, null, match.getSecond());
+
+ // Attempt to find files via ProjectResources.getSourceFiles(); this
+ // is done after the above search since this search won't resolve references
+ FolderConfiguration configuration = getConfiguration();
+ List<ResourceFile> sourceFiles = frameworkResources.getSourceFiles(type, name,
+ configuration);
+ for (ResourceFile file : sourceFiles) {
+ String location = file.getFile().getOsLocation();
+ if (new File(location).exists()) {
+ Path path = new Path(location);
+ openPath(path, null, -1);
return true;
}
}
+
+ } else if (isValueResource(type)) {
+ FolderConfiguration configuration = getConfiguration();
+ Pair<File, Integer> match = findFrameworkValueByConfig(project, type, name,
+ configuration);
+ if (match == null && configuration != null) {
+ match = findFrameworkValueByConfig(project, type, name, null);
+ }
+
+ if (match != null) {
+ Path path = new Path(match.getFirst().getPath());
+ openPath(path, null, match.getSecond());
+ return true;
+ }
}
return false;
}
+ /** Return the set of matching source files for the given resource type and name */
+ private static List<ResourceFile> getResourceFiles(IProject project,
+ ResourceType type, String name, boolean framework,
+ FolderConfiguration configuration) {
+ ProjectResources resources = getResources(project, framework);
+ if (resources == null) {
+ return null;
+ }
+ List<ResourceFile> sourceFiles = resources.getSourceFiles(type, name, configuration);
+ if (sourceFiles != null) {
+ if (sourceFiles.size() > 1 && configuration == null) {
+ // Sort all the files in the base values/ folder first, followed by
+ // everything else
+ List<ResourceFile> first = new ArrayList<ResourceFile>();
+ List<ResourceFile> second = new ArrayList<ResourceFile>();
+ for (ResourceFile file : sourceFiles) {
+ if (FD_VALUES.equals(file.getFolder().getFolder().getName())) {
+ // Found match in value
+ first.add(file);
+ } else {
+ second.add(file);
+ }
+ }
+ first.addAll(second);
+ sourceFiles = first;
+ }
+ }
+
+ return sourceFiles;
+ }
+
+ /** Searches for the given resource for a specific configuration (which may be null) */
+ private static Pair<File, Integer> findFrameworkValueByConfig(IProject project,
+ ResourceType type, String name, FolderConfiguration configuration) {
+ List<ResourceFile> sourceFiles = getResourceFiles(project, type, name, true /* framework*/,
+ configuration);
+ if (sourceFiles != null) {
+ for (ResourceFile resourceFile : sourceFiles) {
+ if (resourceFile.getFile() instanceof FileWrapper) {
+ File file = ((FileWrapper) resourceFile.getFile());
+ if (file.getName().endsWith(EXT_XML)) {
+ // Must have an XML extension
+ Pair<File, Integer> match = findValueInXml(type, name, file);
+ if (match != null) {
+ return match;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
/** Opens a Java class for the given fully qualified class name */
private static boolean openJavaClass(IProject project, String fqcn) {
if (fqcn == null) {
@@ -604,79 +673,132 @@ public class Hyperlinks {
/** Looks up the project member of the given type and the given name */
private static IResource findNonValueFile(IProject project, ResourceType type, String name) {
- String relativePath;
- IResource member;
- String folder = WS_RESOURCES + WS_SEP + type.getName();
- relativePath = folder + WS_SEP + name + '.' + EXT_XML;
- member = project.findMember(relativePath);
- if (member == null) {
- // Search for any file in the directory with the given basename;
- // this is necessary for files like drawables that don't have
- // .xml files. It's an error to have conflicts in basenames for
- // these resources types so this is safe.
- IResource d = project.findMember(folder);
- if (d instanceof IFolder) {
- IFolder dir = (IFolder) d;
- member = findInFolder(name, dir);
+ ProjectResources resources = getResources(project, false /* not framework */);
+ if (resources == null) {
+ return null;
+ }
+ FolderConfiguration configuration = getConfiguration();
+ if (configuration != null) {
+ IResource file = findFileByConfig(type, name, resources, configuration);
+ if (file != null) {
+ return file;
}
+ }
- if (member == null) {
- // Still couldn't find the member; it must not be defined in a "base" directory
- // like "layout"; look in various variations
- ResourceManager manager = ResourceManager.getInstance();
- ProjectResources resources = manager.getProjectResources(project);
-
- ResourceFolderType[] folderTypes = FolderTypeRelationship.getRelatedFolders(type);
- for (ResourceFolderType folderType : folderTypes) {
- if (folderType != ResourceFolderType.VALUES) {
- List<ResourceFolder> folders = resources.getFolders(folderType);
- for (ResourceFolder resourceFolder : folders) {
- if (resourceFolder.getFolder() instanceof IFolderWrapper) {
- IFolderWrapper wrapper =
- (IFolderWrapper) resourceFolder.getFolder();
- IFolder iFolder = wrapper.getIFolder();
- member = findInFolder(name, iFolder);
- if (member != null) {
- break;
- }
- }
- }
- }
+ return findFileByConfig(type, name, resources, null);
+ }
+
+ /**
+ * Find a file for a given named resource, associated with a given folder
+ * configuration
+ */
+ private static IResource findFileByConfig(ResourceType type, String name,
+ ProjectResources resources, FolderConfiguration configuration) {
+ List<ResourceFile> sourceFiles = resources.getSourceFiles(type, name, configuration);
+ if (sourceFiles != null) {
+ for (ResourceFile resourceFile : sourceFiles) {
+ if (resourceFile.getFile() instanceof IFileWrapper) {
+ return ((IFileWrapper) resourceFile.getFile()).getIFile();
}
}
}
- return member;
+ return null;
}
/**
- * Finds a resource of the given name in the given folder, searching for possible file
- * extensions
+ * Returns the current configuration, if the associated UI editor has been initialized
+ * and has an associated configuration
+ *
+ * @return the configuration for this file, or null
*/
- private static IResource findInFolder(String name, IFolder dir) {
- try {
- for (IResource child : dir.members()) {
- String fileName = child.getName();
- int index = fileName.indexOf('.');
- if (index != -1) {
- fileName = fileName.substring(0, index);
+ private static FolderConfiguration getConfiguration() {
+ IEditorPart editor = getEditor();
+ if (editor != null) {
+ if (editor instanceof LayoutEditor) {
+ LayoutEditor layoutEditor = (LayoutEditor) editor;
+ GraphicalEditorPart graphicalEditor = layoutEditor.getGraphicalEditor();
+ if (graphicalEditor != null) {
+ return graphicalEditor.getConfiguration();
+ } else {
+ // TODO: Could try a few more things to get the configuration:
+ // (1) try to look at the file.getPersistentProperty(NAME_CONFIG_STATE)
+ // which will return previously saved state. This isn't necessary today
+ // since no editors seem to be lazily initialized.
+ // (2) attempt to use the configuration from any of the other open
+ // files, especially files in the same directory as this one.
}
- if (fileName.equals(name)) {
- return child;
+ }
+
+ // Create a configuration from the current file
+ IEditorInput editorInput = editor.getEditorInput();
+ if (editorInput instanceof FileEditorInput) {
+ IFile file = ((FileEditorInput) editorInput).getFile();
+ IProject project = file.getProject();
+ ProjectResources pr = ResourceManager.getInstance().getProjectResources(project);
+ ResourceFolder resFolder = pr.getResourceFolder((IFolder) file.getParent());
+ if (resFolder != null) {
+ return resFolder.getConfiguration();
}
}
- } catch (CoreException e) {
- AdtPlugin.log(e, ""); //$NON-NLS-1$
}
return null;
}
+ /** Returns the {@link IAndroidTarget} to be used for looking up system resources */
+ private static IAndroidTarget getTarget(IProject project) {
+ IEditorPart editor = getEditor();
+ if (editor != null) {
+ if (editor instanceof LayoutEditor) {
+ LayoutEditor layoutEditor = (LayoutEditor) editor;
+ GraphicalEditorPart graphicalEditor = layoutEditor.getGraphicalEditor();
+ if (graphicalEditor != null) {
+ return graphicalEditor.getRenderingTarget();
+ }
+ }
+ }
+
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk == null) {
+ return null;
+ }
+
+ return currentSdk.getTarget(project);
+ }
+
+ /** Return either the project resources or the framework resources (or null) */
+ private static ProjectResources getResources(IProject project, boolean framework) {
+ if (framework) {
+ IAndroidTarget target = getTarget(project);
+ if (target == null) {
+ return null;
+ }
+ AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+ if (data == null) {
+ return null;
+ }
+ return data.getFrameworkResources();
+ } else {
+ return ResourceManager.getInstance().getProjectResources(project);
+ }
+ }
+
/**
* Finds a definition of an id attribute in layouts. (Ids can also be defined as
* resources; use {@link #findValueDefinition} to locate it there.)
*/
private static Pair<IFile, IRegion> findIdDefinition(IProject project, String id) {
+ // FIRST look in the same file as the originating request, that's where you usually
+ // want to jump
+ IFile self = getFile();
+ if (self != null && EXT_XML.equals(self.getFileExtension())) {
+ Pair<IFile, IRegion> target = findIdInXml(id, self);
+ if (target != null) {
+ return target;
+ }
+ }
+
// We're currently only searching in the base layout folder.
// The next step is to add global resource reference tracking (which we already
// need to detect unused resources etc) and in that case we can quickly offer
@@ -718,30 +840,39 @@ public class Hyperlinks {
// Search within the files in the values folder and find the value which defines
// the given resource. To be efficient, we will only parse XML files that contain
// a string match of the given token name.
+ FolderConfiguration configuration = getConfiguration();
+ Pair<IFile, IRegion> target = findValueByConfig(project, type, name, configuration);
+ if (target != null) {
+ return target;
+ }
- String folderPath = AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP
- + SdkConstants.FD_VALUES;
+ if (configuration != null) {
+ // Try searching without configuration too; more potential matches
+ return findValueByConfig(project, type, name, configuration);
+ }
- IFolder f = project.getFolder(folderPath);
- if (f.exists()) {
- try {
- // Check XML files in values/
- for (IResource resource : f.members()) {
- if (resource.exists() && !resource.isDerived() && resource instanceof IFile) {
- IFile file = (IFile) resource;
- // Must have an XML extension
- if (EXT_XML.equals(file.getFileExtension())) {
- Pair<IFile, IRegion> target = findValueInXml(type, name, file);
- if (target != null) {
- return target;
- }
+ return null;
+ }
+
+ /** Searches for the given resource for a specific configuration (which may be null) */
+ private static Pair<IFile, IRegion> findValueByConfig(IProject project,
+ ResourceType type, String name, FolderConfiguration configuration) {
+ List<ResourceFile> sourceFiles = getResourceFiles(project, type, name,
+ false /* not framework*/, configuration);
+ if (sourceFiles != null) {
+ for (ResourceFile resourceFile : sourceFiles) {
+ if (resourceFile.getFile() instanceof IFileWrapper) {
+ IFile file = ((IFileWrapper) resourceFile.getFile()).getIFile();
+ if (EXT_XML.equals(file.getFileExtension())) {
+ Pair<IFile, IRegion> target = findValueInXml(type, name, file);
+ if (target != null) {
+ return target;
}
}
}
- } catch (CoreException e) {
- AdtPlugin.log(e, ""); //$NON-NLS-1$
}
}
+
return null;
}
@@ -918,39 +1049,6 @@ public class Hyperlinks {
return Pair.of(type, name);
}
- /**
- * Searches for a resource of a "multi-file" type (like @string) where the value can
- * be found in any file within the folder containing resource of that type (in the
- * case of @string, "values", and in the case of @color, "colors", etc).
- * <p>
- * This method operates on plain {@link File} objects and is intended for searches in
- * the Android platform files; for project-relative searches use
- * {@link #findValueDefinition(File, ResourceType, String)}.
- */
- private static Pair<File, Integer> findValueDefinition(File resourceDir, ResourceType type,
- String name) {
- // Search within the files in the values folder and find the value which defines
- // the given resource. To be efficient, we will only parse XML files that contain
- // a string match of the given token name.
-
- // Check XML files in values/
- File[] children = resourceDir.listFiles();
- if (children == null) {
- return null;
- }
- for (File resource : children) {
- // Must have an XML extension
- if (resource.getName().endsWith(EXT_XML)) {
- Pair<File, Integer> target = findValueInXml(type, name, resource);
- if (target != null) {
- return target;
- }
- }
- }
-
- return null;
- }
-
/** Parses the given file and locates a definition of the given resource */
private static Pair<File, Integer> findValueInXml(ResourceType type, String name, File file) {
// We can't use the StructureModelManager on files outside projects
@@ -981,6 +1079,9 @@ public class Hyperlinks {
if (type == ResourceType.ID) {
// Ids are recorded in <item> tags instead of <id> tags
targetTag = "item"; //$NON-NLS-1$
+ } else if (type == ResourceType.ATTR) {
+ // Attributes seem to be defined in <public> tags
+ targetTag = "public"; //$NON-NLS-1$
}
Element root = document.getDocumentElement();
if (root.getTagName().equals(ROOT_ELEMENT)) {
@@ -1157,20 +1258,30 @@ public class Hyperlinks {
return null;
}
- /** Returns the project applicable to this hyperlink detection */
- private static IProject getProject() {
+ /** Returns the file where the link request originated */
+ private static IFile getFile() {
IEditorPart editor = getEditor();
if (editor != null) {
IEditorInput input = editor.getEditorInput();
if (input instanceof IFileEditorInput) {
IFileEditorInput fileInput = (IFileEditorInput) input;
- return fileInput.getFile().getProject();
+ return fileInput.getFile();
}
}
return null;
}
+ /** Returns the project applicable to this hyperlink detection */
+ private static IProject getProject() {
+ IFile file = getFile();
+ if (file != null) {
+ return file.getProject();
+ }
+
+ return null;
+ }
+
/**
* Hyperlink implementation which delays computing the actual file and offset target
* until it is asked to open the hyperlink
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFileWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFileWrapper.java
index dc022c7..a444cdc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFileWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFileWrapper.java
@@ -123,4 +123,9 @@ public class IFileWrapper implements IAbstractFile {
return null;
}
+
+ @Override
+ public String toString() {
+ return mFile.toString();
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFolderWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFolderWrapper.java
index 265ea33..3c00485 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFolderWrapper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/io/IFolderWrapper.java
@@ -171,4 +171,9 @@ public class IFolderWrapper implements IAbstractFolder {
return null;
}
+
+ @Override
+ public String toString() {
+ return mFolder.toString();
+ }
}