### Eclipse Workspace Patch 1.0 #P org.eclipse.core.resources Index: src/org/eclipse/core/internal/events/ResourceDelta.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/events/ResourceDelta.java,v retrieving revision 1.40 diff -u -r1.40 ResourceDelta.java --- src/org/eclipse/core/internal/events/ResourceDelta.java 18 Sep 2009 14:47:33 -0000 1.40 +++ src/org/eclipse/core/internal/events/ResourceDelta.java 9 Sep 2010 19:46:30 -0000 @@ -376,6 +376,20 @@ return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_HIDDEN); } + protected boolean isFloating() { + //use old info for removals, and new info for added or changed + if ((status & (REMOVED | REMOVED_PHANTOM)) != 0) + return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_FLOATING); + return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_FLOATING); + } + + protected boolean isFlatten() { + //use old info for removals, and new info for added or changed + if ((status & (REMOVED | REMOVED_PHANTOM)) != 0) + return ResourceInfo.isSet(oldInfo.getFlags(), ICoreConstants.M_FLATTEN); + return ResourceInfo.isSet(newInfo.getFlags(), ICoreConstants.M_FLATTEN); + } + protected void setChildren(ResourceDelta[] children) { this.children = children; } @@ -541,6 +555,10 @@ buffer.append(" (team private)"); //$NON-NLS-1$ if (isHidden()) buffer.append(" (hidden)"); //$NON-NLS-1$ + if (isFlatten()) + buffer.append(" (flatten)"); //$NON-NLS-1$ + if (isFloating()) + buffer.append(" (floating)"); //$NON-NLS-1$ } public void writeMarkerDebugString(StringBuffer buffer) { Index: src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java,v retrieving revision 1.45 diff -u -r1.45 RefreshLocalVisitor.java --- src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java 14 Jan 2010 18:18:42 -0000 1.45 +++ src/org/eclipse/core/internal/localstore/RefreshLocalVisitor.java 9 Sep 2010 19:46:30 -0000 @@ -10,6 +10,12 @@ *******************************************************************************/ package org.eclipse.core.internal.localstore; +import org.eclipse.core.internal.resources.ProjectDescription; + +import org.eclipse.core.resources.IResource; + +import java.net.URI; + import org.eclipse.core.internal.resources.*; import org.eclipse.core.internal.utils.Messages; import org.eclipse.core.internal.utils.Policy; @@ -78,16 +84,30 @@ } /* Use the basic file creation protocol since we don't want to create any content on disk. */ info = workspace.createResource(target, false); + if (node.getFlagMasks() != 0) + info.set(node.getFlagMasks()); + /* Mark this resource as having unknown children */ info.set(ICoreConstants.M_CHILDREN_UNKNOWN); target.getLocalManager().updateLocalSync(info, node.getLastModified()); + + if (info.isSet(ICoreConstants.M_LINK)) { + URI localLocation = node.getStore().toURI(); + localLocation = target.getPathVariableManager().convertToRelative(localLocation, true, "PARENT_LOC"); //$NON-NLS-1$ + LinkDescription linkDescription = new LinkDescription(target, localLocation); + Project project = (Project) target.getProject(); + project.getLocalManager().link(target, localLocation, node.fileInfo); + ProjectDescription description = project.internalGetDescription(); + if (description.setLinkLocation(target.getProjectRelativePath(), linkDescription)) + project.writeDescription(IResource.NONE); + } } protected void deleteResource(UnifiedTreeNode node, Resource target) throws CoreException { ResourceInfo info = target.getResourceInfo(false, false); int flags = target.getFlags(info); - //don't delete linked resources - if (ResourceInfo.isSet(flags, ICoreConstants.M_LINK)) { + //don't delete linked resources (but do delete floating resource) + if (ResourceInfo.isSet(flags, ICoreConstants.M_LINK) && !ResourceInfo.isSet(flags, ICoreConstants.M_FLOATING)) { //just clear local sync info info = target.getResourceInfo(false, true); //handle concurrent deletion Index: src/org/eclipse/core/internal/localstore/UnifiedTree.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTree.java,v retrieving revision 1.54 diff -u -r1.54 UnifiedTree.java --- src/org/eclipse/core/internal/localstore/UnifiedTree.java 20 Apr 2010 15:48:36 -0000 1.54 +++ src/org/eclipse/core/internal/localstore/UnifiedTree.java 9 Sep 2010 19:46:30 -0000 @@ -132,77 +132,155 @@ if (!parent.getProject().isAccessible()) return; - // get the list of resources in the file system - // don't ask for local children if we know it doesn't exist locally - IFileInfo[] list = node.existsInFileSystem() ? getLocalList(node) : NO_CHILDREN; - int localIndex = 0; - - // See if the children of this resource have been computed before - ResourceInfo resourceInfo = parent.getResourceInfo(false, false); - int flags = parent.getFlags(resourceInfo); - boolean unknown = ResourceInfo.isSet(flags, ICoreConstants.M_CHILDREN_UNKNOWN); - - // get the list of resources in the workspace - if (!unknown && (parentType == IResource.FOLDER || parentType == IResource.PROJECT) && parent.exists(flags, true)) { - IResource target = null; - UnifiedTreeNode child = null; - IResource[] members; - try { - members = ((IContainer) parent).members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); - } catch (CoreException e) { - members = NO_RESOURCES; - } - int workspaceIndex = 0; - //iterate simultaneously over file system and workspace members - while (workspaceIndex < members.length) { - target = members[workspaceIndex]; - String name = target.getName(); - IFileInfo localInfo = localIndex < list.length ? list[localIndex] : null; - int comp = localInfo != null ? name.compareTo(localInfo.getName()) : -1; - //special handling for linked resources - if (target.isLinked()) { - //child will be null if location is undefined - child = createChildForLinkedResource(target); - workspaceIndex++; - //if there is a matching local file, skip it - it will be blocked by the linked resource - if (comp == 0) + boolean shouldBeFloating = (((IContainer) node.resource).isFlatten()); + if (shouldBeFloating) { + // create linked resources for each given file store + // get the list of resources in the file system + // don't ask for local children if we know it doesn't exist locally + IFileStore[] list = node.existsInFileSystem() ? getLocalFlattenList(node) : new IFileStore[0]; + int localIndex = 0; + + Project project = (Project) parent.getProject(); + UniqueFileStoreName[] uniqueList = generateUniqueList(list); + + // See if the children of this resource have been computed before + ResourceInfo resourceInfo = parent.getResourceInfo(false, false); + int flags = parent.getFlags(resourceInfo); + boolean unknown = ResourceInfo.isSet(flags, ICoreConstants.M_CHILDREN_UNKNOWN); + + // get the list of resources in the workspace + if (!unknown && (parentType == IResource.FOLDER || parentType == IResource.PROJECT) && parent.exists(flags, true)) { + IResource target = null; + UnifiedTreeNode child = null; + IResource[] members; + try { + members = ((IContainer) parent).members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); + } catch (CoreException e) { + members = NO_RESOURCES; + } + int workspaceIndex = 0; + //iterate simultaneously over file system and workspace members + while (workspaceIndex < members.length) { + target = members[workspaceIndex]; + String name = target.getName(); + UniqueFileStoreName info = localIndex < uniqueList.length ? uniqueList[localIndex] : null; + int comp = info != null ? name.compareTo(info.name) : -1; + //special handling for linked resources + if (!target.isLinked()) { + // a flatten folder can only contain linked resources + child = createNode(target, null, null, true); + workspaceIndex++; + } else if (!target.isFloating()) { + child = createChildForLinkedResource(target); + workspaceIndex++; + //if there is a matching local file (a floating linked resource), skip it - it will be blocked by the linked resource + if (comp == 0) + localIndex++; + } else if (comp == 0) { + // resource exists in workspace and file system --> localInfo is non-null + child = createNode(target, info.store, info.info, true); + localIndex++; + workspaceIndex++; + } else if (comp > 0) { + // resource exists only in file system + //don't create a node for symbolic links that create a cycle + child = createNewFloatingLinkedResourceNode(project, node, info); localIndex++; - } else if (comp == 0) { - // resource exists in workspace and file system --> localInfo is non-null - //create workspace-only node for symbolic link that creates a cycle - if (localInfo.getAttribute(EFS.ATTRIBUTE_SYMLINK) && localInfo.isDirectory() && isRecursiveLink(node.getStore(), localInfo)) + } else { + // resource exists only in the workspace child = createNode(target, null, null, true); - else - child = createNode(target, null, localInfo, true); - localIndex++; - workspaceIndex++; - } else if (comp > 0) { - // resource exists only in file system - //don't create a node for symbolic links that create a cycle - if (localInfo.getAttribute(EFS.ATTRIBUTE_SYMLINK) && localInfo.isDirectory() && isRecursiveLink(node.getStore(), localInfo)) - child = null; - else - child = createChildNodeFromFileSystem(node, localInfo); - localIndex++; - } else { - // resource exists only in the workspace - child = createNode(target, null, null, true); - workspaceIndex++; + workspaceIndex++; + } + if (child != null) + addChildToTree(node, child); } - if (child != null) - addChildToTree(node, child); + /* process any remaining resource from the file system */ + addChildrenFromFileSystem(project, node, uniqueList, localIndex); } - } - /* process any remaining resource from the file system */ - addChildrenFromFileSystem(node, list, localIndex); + /* Mark the children as now known */ + if (unknown) { + // Don't open the info - we might not be inside a workspace-modifying operation + resourceInfo = parent.getResourceInfo(false, false); + if (resourceInfo != null) + resourceInfo.clear(ICoreConstants.M_CHILDREN_UNKNOWN); + } + } else { + // get the list of resources in the file system + // don't ask for local children if we know it doesn't exist locally + IFileInfo[] list = node.existsInFileSystem() ? getLocalList(node) : NO_CHILDREN; + int localIndex = 0; + + // See if the children of this resource have been computed before + ResourceInfo resourceInfo = parent.getResourceInfo(false, false); + int flags = parent.getFlags(resourceInfo); + boolean unknown = ResourceInfo.isSet(flags, ICoreConstants.M_CHILDREN_UNKNOWN); + + // get the list of resources in the workspace + if (!unknown && (parentType == IResource.FOLDER || parentType == IResource.PROJECT) && parent.exists(flags, true)) { + IResource target = null; + UnifiedTreeNode child = null; + IResource[] members; + try { + members = ((IContainer) parent).members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); + } catch (CoreException e) { + members = NO_RESOURCES; + } + int workspaceIndex = 0; + //iterate simultaneously over file system and workspace members + while (workspaceIndex < members.length) { + target = members[workspaceIndex]; + String name = target.getName(); + IFileInfo localInfo = localIndex < list.length ? list[localIndex] : null; + int comp = localInfo != null ? name.compareTo(localInfo.getName()) : -1; + //special handling for linked resources + if (target.isFloating()) { + // remove all floating resources + child = createNode(target, null, null, true); + workspaceIndex++; + } else if (target.isLinked()) { + //child will be null if location is undefined + child = createChildForLinkedResource(target); + workspaceIndex++; + //if there is a matching local file, skip it - it will be blocked by the linked resource + if (comp == 0) + localIndex++; + } else if (comp == 0) { + // resource exists in workspace and file system --> localInfo is non-null + //create workspace-only node for symbolic link that creates a cycle + if (localInfo.getAttribute(EFS.ATTRIBUTE_SYMLINK) && localInfo.isDirectory() && isRecursiveLink(node.getStore(), localInfo)) + child = createNode(target, null, null, true); + else + child = createNode(target, null, localInfo, true); + localIndex++; + workspaceIndex++; + } else if (comp > 0) { + // resource exists only in file system + //don't create a node for symbolic links that create a cycle + if (localInfo.getAttribute(EFS.ATTRIBUTE_SYMLINK) && localInfo.isDirectory() && isRecursiveLink(node.getStore(), localInfo)) + child = null; + else + child = createChildNodeFromFileSystem(node, localInfo); + localIndex++; + } else { + // resource exists only in the workspace + child = createNode(target, null, null, true); + workspaceIndex++; + } + if (child != null) + addChildToTree(node, child); + } + } + /* process any remaining resource from the file system */ + addChildrenFromFileSystem(node, list, localIndex); - /* Mark the children as now known */ - if (unknown) { - // Don't open the info - we might not be inside a workspace-modifying operation - resourceInfo = parent.getResourceInfo(false, false); - if (resourceInfo != null) - resourceInfo.clear(ICoreConstants.M_CHILDREN_UNKNOWN); + /* Mark the children as now known */ + if (unknown) { + // Don't open the info - we might not be inside a workspace-modifying operation + resourceInfo = parent.getResourceInfo(false, false); + if (resourceInfo != null) + resourceInfo.clear(ICoreConstants.M_CHILDREN_UNKNOWN); + } } /* if we added children, add the childMarker separator */ @@ -210,6 +288,66 @@ addChildrenMarker(); } + private static class UniqueFileStoreName { + public UniqueFileStoreName(String name, IFileStore store, IFileInfo info) { + this.name = name; + this.store = store; + this.info = info; + } + + public String name; + public IFileStore store; + public IFileInfo info; + } + + // The names are suffixed with the directory in which they belong, if there's a conflict. + // For instance, if two files (foo/bar.txt and folder/bar.txt) shared the same name, the second + // file will have its immediate parent appended as follows: "bar.txt (folder)". + // if multiple files share the same name, the parent directory names are appended with a "-" + // delimiter, as follows: "bar.txt (root-folder)" since the "/" delimiter isn't a valid name + // character. + private UniqueFileStoreName[] generateUniqueList(IFileStore[] list) { + // the list is already sorted by name, so identical named items are consecutives + UniqueFileStoreName[] uniqueList = new UniqueFileStoreName[list.length]; + boolean changed = false; + uniqueList[0] = new UniqueFileStoreName(list[0].getName(), list[0], list[0].fetchInfo()); + for (int i = 1; i < list.length; i++) { + String name = list[i].getName(); + if (list[i - 1].getName().equals(name)) { + IFileStore parent = list[i].getParent(); + String suffix = parent.getName(); + String tentativeName = name + " (" + suffix + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + while (nameExistsInList(tentativeName, uniqueList, list, i - 1)) { + parent = parent.getParent(); + suffix = parent.getName() + ' ' + suffix; + tentativeName = name + " (" + suffix + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + } + name = tentativeName; + changed = true; + } + uniqueList[i] = new UniqueFileStoreName(name, list[i], list[i].fetchInfo()); + } + if (changed) { + Arrays.sort(uniqueList, new Comparator() { + public int compare(Object arg0, Object arg1) { + UniqueFileStoreName a = (UniqueFileStoreName) arg0; + UniqueFileStoreName b = (UniqueFileStoreName) arg1; + return a.name.compareTo(b.name); + } + }); + } + return uniqueList; + } + + private boolean nameExistsInList(String tentativeName, UniqueFileStoreName[] uniqueList, IFileStore[] list, int i) { + while (i >= 0 && list[i].getName().equals(list[i + 1].getName())) { + if (uniqueList[i].name.equals(tentativeName)) + return true; + i--; + } + return false; + } + protected void addChildrenFromFileSystem(UnifiedTreeNode node, IFileInfo[] childInfos, int index) { if (childInfos == null) return; @@ -221,6 +359,21 @@ } } + protected void addChildrenFromFileSystem(Project project, UnifiedTreeNode node, UniqueFileStoreName[] elements, int index) { + if (elements == null) + return; + for (int i = index; i < elements.length; i++) { + UnifiedTreeNode child = createNewFloatingLinkedResourceNode(project, node, elements[i]); + addChildToTree(node, child); + } + } + + private UnifiedTreeNode createNewFloatingLinkedResourceNode(Project project, UnifiedTreeNode node, UniqueFileStoreName element) { + UnifiedTreeNode child = createChildNodeFromFileSystem(node, element); + child.setFlagMasks(ICoreConstants.M_LINK | ICoreConstants.M_FLOATING); + return child; + } + protected void addChildrenMarker() { addElementToQueue(childrenMarker); } @@ -283,6 +436,16 @@ } /** + * Creates a child node for a location in the file system. Does nothing and returns null if the location does not correspond to a valid file/folder. + */ + protected UnifiedTreeNode createChildNodeFromFileSystem(UnifiedTreeNode parent, UniqueFileStoreName element) { + IPath childPath = parent.getResource().getFullPath().append(element.name); + int type = element.info.isDirectory() ? IResource.FOLDER : IResource.FILE; + IResource target = getWorkspace().newResource(childPath, type); + return createNode(target, element.store, element.info, false); + } + + /** * Factory method for creating a node for this tree. If the file exists on * disk, either the parent store or child store can be provided. Providing * only the parent store avoids creation of the child store in cases where @@ -335,13 +498,57 @@ return level; } + protected IFileStore[] getLocalFlattenList(UnifiedTreeNode node) { + try { + final IFileStore store = node.getStore(); + IFileStore[] list = fileTree != null ? fileTree.getChildStores(store) : store.childStores(EFS.NONE, null); + if (list == null || list.length == 0) + return new IFileStore[0]; + list = (IFileStore[]) ((Resource) node.getResource()).filterChildren(list, false); + + // flatten the directory structure + ArrayList finalList = new ArrayList(); + Stack foldersToFlatten = new Stack(); + for (int i = 0; i < list.length; i++) { + if (list[i].fetchInfo().isDirectory()) + foldersToFlatten.push(list[i]); + else + finalList.add(list[i]); + } + while (!foldersToFlatten.isEmpty()) { + IFileStore folder = (IFileStore) foldersToFlatten.pop(); + IFileStore[] children = fileTree != null ? fileTree.getChildStores(folder) : folder.childStores(EFS.NONE, null); + children = (IFileStore[]) ((Resource) node.getResource()).filterChildren(children, false); + for (int i = 0; i < children.length; i++) { + if (children[i].fetchInfo().isDirectory()) + foldersToFlatten.push(children[i]); + else + finalList.add(children[i]); + } + } + + IFileStore[] uriList = (IFileStore[]) finalList.toArray(new IFileStore[0]); + Arrays.sort(uriList, new Comparator() { + public int compare(Object arg0, Object arg1) { + IFileStore a = (IFileStore) arg0; + IFileStore b = (IFileStore) arg1; + return a.getName().compareTo(b.getName()); + } + }); + return uriList; + } catch (CoreException e) { + //treat failure to access the directory as a non-existent directory + return new IFileStore[0]; + } + } + protected IFileInfo[] getLocalList(UnifiedTreeNode node) { try { final IFileStore store = node.getStore(); IFileInfo[] list = fileTree != null ? fileTree.getChildInfos(store) : store.childInfos(EFS.NONE, null); if (list == null || list.length == 0) return NO_CHILDREN; - list = ((Resource) node.getResource()).filterChildren(list, false); + list = (IFileInfo[]) ((Resource) node.getResource()).filterChildren(list, false); int size = list.length; if (size > 1) quickSort(list, 0, size - 1); Index: src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java,v retrieving revision 1.24 diff -u -r1.24 UnifiedTreeNode.java --- src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java 14 Oct 2009 15:17:19 -0000 1.24 +++ src/org/eclipse/core/internal/localstore/UnifiedTreeNode.java 9 Sep 2010 19:46:30 -0000 @@ -28,6 +28,7 @@ protected IResource resource; protected IFileStore store; protected UnifiedTree tree; + protected int flags = 0; public UnifiedTreeNode(UnifiedTree tree, IResource resource, IFileStore store, IFileInfo fileInfo, boolean existsWorkspace) { this.tree = tree; @@ -60,6 +61,10 @@ return fileInfo == null ? 0 : fileInfo.getLastModified(); } + public int getFlagMasks() { + return flags; + } + public int getLevel() { return tree.getLevel(); } @@ -129,6 +134,10 @@ this.child = child; } + public void setFlagMasks(int flags) { + this.flags = flags; + } + public void setResource(IResource resource) { this.resource = resource; } Index: src/org/eclipse/core/internal/resources/Filter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Filter.java,v retrieving revision 1.10 diff -u -r1.10 Filter.java --- src/org/eclipse/core/internal/resources/Filter.java 3 May 2010 14:23:26 -0000 1.10 +++ src/org/eclipse/core/internal/resources/Filter.java 9 Sep 2010 19:46:31 -0000 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.core.internal.resources; +import org.eclipse.core.filesystem.IFileStore; + import org.eclipse.core.internal.utils.Policy; import java.util.Iterator; @@ -86,18 +88,51 @@ return (getType() & IResourceFilterDescription.FILES) != 0; } - public static IFileInfo[] filter(IProject project, LinkedList/*Filter*/includeFilters, LinkedList/*Filter*/excludeFilters, IContainer parent, IFileInfo[] list) throws CoreException { - IFileInfo[] result = filterIncludes(project, includeFilters, parent, list); - return filterExcludes(project, excludeFilters, parent, result); + interface IFileInfoAccessor + { + IFileInfo get(Object obj); + Object[] newArray(int length); + } + + static class FileInfoAccessor implements IFileInfoAccessor { + public IFileInfo get(Object obj) { + return (IFileInfo) obj; + } + + public Object[] newArray(int length) { + return new IFileInfo[length]; + } + } + + static class FileStoreAccessor implements IFileInfoAccessor { + public IFileInfo get(Object obj) { + return ((IFileStore) obj).fetchInfo(); + } + + public Object[] newArray(int length) { + return new IFileStore[length]; + } + } + + public static Object[] filter(IProject project, LinkedList/*Filter*/includeFilters, LinkedList/*Filter*/excludeFilters, IContainer parent, Object[] list) throws CoreException { + + IFileInfoAccessor accessor; + if (list[0] instanceof IFileInfo) + accessor = new FileInfoAccessor(); + else + accessor = new FileStoreAccessor(); + + Object[] result = filterIncludes(project, includeFilters, parent, list, accessor); + return filterExcludes(project, excludeFilters, parent, result, accessor); } - public static IFileInfo[] filterIncludes(IProject project, LinkedList/*Filter*/filters, IContainer parent, IFileInfo[] list) throws CoreException { + public static Object[] filterIncludes(IProject project, LinkedList/*Filter*/filters, IContainer parent, Object[] list, IFileInfoAccessor accessor) throws CoreException { if (filters.size() > 0) { - IFileInfo[] result = new IFileInfo[list.length]; + Object[] result = accessor.newArray(list.length); int outputIndex = 0; - + for (int i = 0; i < list.length; i++) { - IFileInfo info = list[i]; + IFileInfo info = accessor.get(list[i]); Iterator objIt = filters.iterator(); boolean filtersWereApplicable = false; while (objIt.hasNext()) { @@ -105,16 +140,16 @@ if (filter.appliesTo(info)) { filtersWereApplicable = true; if (filter.match(parent, info)) { - result[outputIndex++] = info; + result[outputIndex++] = list[i]; break; } } } if (!filtersWereApplicable) - result[outputIndex++] = info; + result[outputIndex++] = list[i]; } if (outputIndex != result.length) { - IFileInfo[] tmp = new IFileInfo[outputIndex]; + Object[] tmp = accessor.newArray(outputIndex); System.arraycopy(result, 0, tmp, 0, outputIndex); result = tmp; } @@ -123,13 +158,13 @@ return list; } - public static IFileInfo[] filterExcludes(IProject project, LinkedList/*Filter*/filters, IContainer parent, IFileInfo[] list) throws CoreException { + public static Object[] filterExcludes(IProject project, LinkedList/*Filter*/filters, IContainer parent, Object[] list, IFileInfoAccessor accessor) throws CoreException { if (filters.size() > 0) { - IFileInfo[] result = new IFileInfo[list.length]; + Object[] result = accessor.newArray(list.length); int outputIndex = 0; for (int i = 0; i < list.length; i++) { - IFileInfo info = list[i]; + IFileInfo info = accessor.get(list[i]); Iterator objIt = filters.iterator(); boolean shouldBeExcluded = false; while (objIt.hasNext()) { @@ -142,10 +177,10 @@ } } if (!shouldBeExcluded) - result[outputIndex++] = info; + result[outputIndex++] = list[i]; } if (outputIndex != result.length) { - IFileInfo[] tmp = new IFileInfo[outputIndex]; + Object[] tmp = accessor.newArray(outputIndex); System.arraycopy(result, 0, tmp, 0, outputIndex); result = tmp; } Index: src/org/eclipse/core/internal/resources/ICoreConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ICoreConstants.java,v retrieving revision 1.31 diff -u -r1.31 ICoreConstants.java --- src/org/eclipse/core/internal/resources/ICoreConstants.java 20 Jan 2010 17:02:26 -0000 1.31 +++ src/org/eclipse/core/internal/resources/ICoreConstants.java 9 Sep 2010 19:46:31 -0000 @@ -64,6 +64,16 @@ */ static final int M_VIRTUAL = 0x80000; /** + * Marks this resource as flatten. + * @since 3.7 + */ + static final int M_FLATTEN = 0x400000; + /** + * Marks this resource as floating. + * @since 3.7 + */ + static final int M_FLOATING = 0x800000; + /** * The file has no content description. * @since 3.0 */ Index: src/org/eclipse/core/internal/resources/LinkDescription.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/LinkDescription.java,v retrieving revision 1.17 diff -u -r1.17 LinkDescription.java --- src/org/eclipse/core/internal/resources/LinkDescription.java 8 Mar 2010 11:51:32 -0000 1.17 +++ src/org/eclipse/core/internal/resources/LinkDescription.java 9 Sep 2010 19:46:31 -0000 @@ -79,7 +79,7 @@ return type; } - public boolean isGroup() { + public boolean isVirtual() { return localLocation.equals(VIRTUAL_LOCATION); } Index: src/org/eclipse/core/internal/resources/Project.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Project.java,v retrieving revision 1.173 diff -u -r1.173 Project.java --- src/org/eclipse/core/internal/resources/Project.java 27 Apr 2010 09:16:15 -0000 1.173 +++ src/org/eclipse/core/internal/resources/Project.java 9 Sep 2010 19:46:34 -0000 @@ -1112,7 +1112,7 @@ if (parent != null && !parent.exists() && parent.getType() == FOLDER) ((Folder) parent).ensureExists(Policy.monitorFor(null)); if (!toLink.exists() || !toLink.isLinked()) { - if (newLink.isGroup()) + if (newLink.isVirtual()) ((Folder) toLink).create(IResource.REPLACE | IResource.VIRTUAL, true, null); else toLink.createLink(newLink.getLocationURI(), IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null); Index: src/org/eclipse/core/internal/resources/Resource.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Resource.java,v retrieving revision 1.190 diff -u -r1.190 Resource.java --- src/org/eclipse/core/internal/resources/Resource.java 20 Apr 2010 15:48:36 -0000 1.190 +++ src/org/eclipse/core/internal/resources/Resource.java 9 Sep 2010 19:46:34 -0000 @@ -17,6 +17,14 @@ *******************************************************************************/ package org.eclipse.core.internal.resources; +import org.eclipse.core.internal.utils.Messages; +import org.eclipse.core.internal.utils.Policy; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.OperationCanceledException; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + import java.net.URI; import java.net.URISyntaxException; import java.util.*; @@ -663,10 +671,13 @@ ResourceInfo info = workspace.createResource(this, false); if ((updateFlags & IResource.HIDDEN) != 0) info.set(M_HIDDEN); + if ((updateFlags & IResource.FLATTEN) != 0) + info.set(M_FLATTEN); + info.set(M_LINK); localLocation = FileUtil.canonicalURI(localLocation); LinkDescription linkDescription = new LinkDescription(this, localLocation); - if (linkDescription.isGroup()) + if (linkDescription.isVirtual()) info.set(M_VIRTUAL); getLocalManager().link(this, localLocation, fileInfo); monitor.worked(Policy.opWork * 5 / 100); @@ -2064,7 +2075,7 @@ info.setDirectory(currentResource.getType() == IResource.FOLDER); fileInfo = info; } - IFileInfo[] filtered = parent.filterChildren(new IFileInfo[] {fileInfo}, throwExeception); + Object[] filtered = parent.filterChildren(new Object[] {fileInfo}, throwExeception); if (filtered.length == 0) return true; } @@ -2073,11 +2084,20 @@ } return false; } - - public IFileInfo[] filterChildren(IFileInfo[] list, boolean throwException) throws CoreException { + + /** + * Filter the list of file entries according to the existing resource filters + * @param list can be either an array of IFileInfo or IFileStore + * @param throwException + * @return the filtered list (either an array of IFileInfo or IFileStore + * @throws CoreException + */ + public Object[] filterChildren(Object[] list, boolean throwException) throws CoreException { Project project = (Project) getProject(); if (project == null) return list; + if (list.length == 0) + return list; final ProjectDescription description = project.internalGetDescription(); if (description == null) return list; @@ -2181,4 +2201,89 @@ setLinkLocation(URIUtil.toURI(location.toPortableString()), updateFlags, monitor); } } + + /* + * (non-Javadoc) + * + * @see IContainer#isFlatten() + */ + public boolean isFloating() { + ResourceInfo info = getResourceInfo(false, false); + return info != null && info.isSet(M_FLOATING); + } + + /* + * Set the floating flag + */ + public void setFloating(boolean floating) { + ResourceInfo info = getResourceInfo(true, true); + if (info != null) { + if (floating) + info.isSet(M_FLOATING); + else + info.clear(M_FLOATING); + } + } + + /* + * (non-Javadoc) + * + * @see IContainer#isFlatten() + */ + public boolean isFlatten() { + ResourceInfo info = getResourceInfo(false, false); + return info != null && info.isSet(M_FLATTEN); + } + + /** + * + * @exception CoreException + * + * @see #isFlatten() + * @since 3.7 + */ + public void setFlatten(boolean flatten, int updateFlags, IProgressMonitor monitor) throws CoreException { + monitor = Policy.monitorFor(monitor); + try { + String message = NLS.bind(Messages.resources_settingFlattenFlag, getFullPath()); + monitor.beginTask(message, Policy.totalWork); + Policy.checkCanceled(monitor); + checkValidPath(path, FOLDER | PROJECT, true); + final ISchedulingRule rule = workspace.getRuleFactory().createRule(this); + try { + workspace.prepareOperation(rule, monitor); + workspace.beginOperation(true); + monitor.worked(Policy.opWork * 5 / 100); + ResourceInfo info = getResourceInfo(true, true); + // ignore attempts to set flatten flag on anything except projects and folders + if (info.getType() != PROJECT && info.getType() != FOLDER) + return; + + if (flatten) + info.set(ICoreConstants.M_FLATTEN); + else { + info.clear(ICoreConstants.M_FLATTEN); + } + //refresh to update resources below this container location + if (getType() != IResource.FILE) { + //refresh either in background or foreground + if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) { + workspace.refreshManager.refresh(this); + monitor.worked(Policy.opWork * 90 / 100); + } else { + refreshLocal(DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 90 / 100)); + } + } else + monitor.worked(Policy.opWork * 90 / 100); + } catch (OperationCanceledException e) { + workspace.getWorkManager().operationCanceled(); + throw e; + } finally { + workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork)); + } + } finally { + monitor.done(); + } + } + } Index: src/org/eclipse/core/internal/resources/Workspace.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Workspace.java,v retrieving revision 1.235 diff -u -r1.235 Workspace.java --- src/org/eclipse/core/internal/resources/Workspace.java 10 Mar 2010 21:45:36 -0000 1.235 +++ src/org/eclipse/core/internal/resources/Workspace.java 9 Sep 2010 19:46:35 -0000 @@ -13,6 +13,8 @@ *******************************************************************************/ package org.eclipse.core.internal.resources; +import org.eclipse.core.resources.IResource; + import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -985,6 +987,8 @@ info.set(M_TEAM_PRIVATE_MEMBER); if ((updateFlags & IResource.HIDDEN) != 0) info.set(M_HIDDEN); + if ((updateFlags & IResource.FLATTEN) != 0) + info.set(M_FLATTEN); // if ((updateFlags & IResource.VIRTUAL) != 0) // info.set(M_VIRTUAL); return info; Index: src/org/eclipse/core/internal/utils/Messages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/Messages.java,v retrieving revision 1.45 diff -u -r1.45 Messages.java --- src/org/eclipse/core/internal/utils/Messages.java 25 Apr 2010 23:15:36 -0000 1.45 +++ src/org/eclipse/core/internal/utils/Messages.java 9 Sep 2010 19:46:35 -0000 @@ -276,6 +276,7 @@ public static String resources_settingContents; public static String resources_settingDefaultCharsetContainer; public static String resources_settingDerivedFlag; + public static String resources_settingFlattenFlag; public static String resources_shutdown; public static String resources_shutdownProblems; public static String resources_snapInit; Index: src/org/eclipse/core/internal/utils/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/utils/messages.properties,v retrieving revision 1.143 diff -u -r1.143 messages.properties --- src/org/eclipse/core/internal/utils/messages.properties 25 Apr 2010 23:15:36 -0000 1.143 +++ src/org/eclipse/core/internal/utils/messages.properties 9 Sep 2010 19:46:36 -0000 @@ -275,6 +275,7 @@ resources_settingDefaultCharsetContainer = Setting default character set for resource ''{0}''. resources_settingContents = Setting contents for ''{0}''. resources_settingDerivedFlag = Setting derived flag for resource ''{0}''. +resources_settingFlattenFlag = Setting flatten flag for resource ''{0}''. resources_shutdown = Workspace was not properly initialized or has already shutdown. resources_shutdownProblems = Problem on shutdown. resources_snapInit = Could not initialize snapshot file. Index: src/org/eclipse/core/resources/IContainer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IContainer.java,v retrieving revision 1.45 diff -u -r1.45 IContainer.java --- src/org/eclipse/core/resources/IContainer.java 5 Mar 2010 11:53:28 -0000 1.45 +++ src/org/eclipse/core/resources/IContainer.java 9 Sep 2010 19:46:36 -0000 @@ -524,4 +524,22 @@ * @since 3.6 */ public IResourceFilterDescription[] getFilters() throws CoreException; + + /** + * + * @return true if this container flattens his file system hierarchy + * + * @see #setFlatten(boolean, int, IProgressMonitor) + * @since 3.7 + */ + public boolean isFlatten(); + + /** + * + * @exception CoreException + * + * @see #isFlatten() + * @since 3.7 + */ + public void setFlatten(boolean flatten, int updateFlags, IProgressMonitor monitor) throws CoreException; } Index: src/org/eclipse/core/resources/IResource.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IResource.java,v retrieving revision 1.118 diff -u -r1.118 IResource.java --- src/org/eclipse/core/resources/IResource.java 19 May 2010 16:01:04 -0000 1.118 +++ src/org/eclipse/core/resources/IResource.java 9 Sep 2010 19:46:38 -0000 @@ -291,6 +291,16 @@ */ public static final int VIRTUAL = 0x2000; + /** + * Update flag constant (bit mask value 0x4000) indicating that a + * container should flatten the underlying file system hierarchy. + * + * @see IContainer#setFlatten(boolean, int, IProgressMonitor) + * @see IContainer#isFlatten() + * @since 3.7 + */ + public static final int FLATTEN = 0x4000; + /*==================================================================== * Other constants: *====================================================================*/ @@ -1735,6 +1745,20 @@ public boolean isVirtual(); /** + * Returns whether this resource is a floating resource. Returns true + * for resources that have been generated by a flatten container refresh operation. + * Returns false in all other cases, including + * the case where this resource does not exist. The workspace root and projects + * currently cannot be floating. + * + * @return true if this resource is floating, and + * false otherwise + * @see IContainer#setFlatten(boolean, int, IProgressMonitor) + * @since 3.7 + */ + public boolean isFloating(); + + /** * Returns true if this resource has been linked to * a location other than the default location calculated by the platform. This * location can be outside the project's content area or another location #P org.eclipse.ui.ide Index: plugin.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/plugin.properties,v retrieving revision 1.157 diff -u -r1.157 plugin.properties --- plugin.properties 1 Jun 2010 19:22:30 -0000 1.157 +++ plugin.properties 9 Sep 2010 19:46:40 -0000 @@ -93,6 +93,8 @@ GoToResourceAction.label = &Resource... DecoratorLinkedResource.label = Linked Resources DecoratorLinkedResource.description = Adds an icon decoration to linked resources. +DecoratorFloatingResource.label = Floating Resources +DecoratorFloatingResource.description = Adds an icon decoration to floating resources. DecoratorVirtualResource.label = Virtual Folders DecoratorVirtualResource.description = Shows an icon for virtual folders. DecoratorSpecificContentType.label = File Icons Based On Content Analysis Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/plugin.xml,v retrieving revision 1.304 diff -u -r1.304 plugin.xml --- plugin.xml 12 May 2010 20:15:28 -0000 1.304 +++ plugin.xml 9 Sep 2010 19:46:41 -0000 @@ -376,6 +376,23 @@ lightweight="true" adaptable="true" location="BOTTOM_RIGHT" + label="%DecoratorFloatingResource.label" + class="org.eclipse.ui.internal.ide.FloatingResourceDecorator" + state="true" + id="org.eclipse.ui.FloatingResourceDecorator"> + + %DecoratorFloatingResource.description + + + + + + + LinkedResourceDecorator. + */ + public FloatingResourceDecorator() { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(ILabelProviderListener) + */ + public void addListener(ILabelProviderListener listener) { + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() + */ + public void dispose() { + // no resources to dispose + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String) + */ + public boolean isLabelProperty(Object element, String property) { + return false; + } + + /** + * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener listener) { + } + + /** + * Adds the linked resource overlay if the given element is a linked + * resource. + * + * @param element element to decorate + * @param decoration The decoration we are adding to + * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(Object, IDecoration) + */ + public void decorate(Object element, IDecoration decoration) { + + if (element instanceof IResource == false) { + return; + } + IResource resource = (IResource) element; + if (resource.isFloating()) + decoration.addOverlay(FLOATING); + } + +} Index: src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java,v retrieving revision 1.89 diff -u -r1.89 IDEWorkbenchMessages.java --- src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java 12 May 2010 13:26:39 -0000 1.89 +++ src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java 9 Sep 2010 19:46:43 -0000 @@ -613,6 +613,7 @@ public static String ResourceInfo_folder; public static String ResourceInfo_project; public static String ResourceInfo_linkedFile; + public static String ResourceInfo_floatingFile; public static String ResourceInfo_linkedFolder; public static String ResourceInfo_virtualFolder; public static String ResourceInfo_unknown; @@ -622,6 +623,8 @@ public static String ResourceInfo_fileNotExist; public static String ResourceInfo_path; public static String ResourceInfo_lastModified; + public static String ResourceInfo_folderHierarchy; + public static String ResourceInfo_flatten; public static String ResourceInfo_fileEncodingTitle; public static String ResourceInfo_fileContentEncodingFormat; public static String ResourceInfo_fileContainerEncodingFormat; Index: src/org/eclipse/ui/internal/ide/LinkedResourceDecorator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/LinkedResourceDecorator.java,v retrieving revision 1.13 diff -u -r1.13 LinkedResourceDecorator.java --- src/org/eclipse/ui/internal/ide/LinkedResourceDecorator.java 20 Jan 2010 17:02:29 -0000 1.13 +++ src/org/eclipse/ui/internal/ide/LinkedResourceDecorator.java 9 Sep 2010 19:46:43 -0000 @@ -87,7 +87,7 @@ return; } IResource resource = (IResource) element; - if (resource.isLinked() && !resource.isVirtual()) { + if (resource.isLinked() && !resource.isVirtual() && !resource.isFloating()) { IFileInfo fileInfo = null; URI location = resource.getLocationURI(); if (location != null) { Index: src/org/eclipse/ui/internal/ide/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties,v retrieving revision 1.214 diff -u -r1.214 messages.properties --- src/org/eclipse/ui/internal/ide/messages.properties 18 May 2010 12:18:07 -0000 1.214 +++ src/org/eclipse/ui/internal/ide/messages.properties 9 Sep 2010 19:46:44 -0000 @@ -570,6 +570,7 @@ ResourceInfo_locked = L&ocked ResourceInfo_archive = Ar&chive ResourceInfo_derived = Deri&ved +ResourceInfo_flatten = &Flatten ResourceInfo_type = &Type: ResourceInfo_location = &Location: ResourceInfo_resolvedLocation = Resolved locatio&n: @@ -632,6 +633,7 @@ ResourceInfo_folder = Folder ResourceInfo_project = Project ResourceInfo_linkedFile = Linked File +ResourceInfo_floatingFile = Floating File ResourceInfo_linkedFolder = Linked Folder ResourceInfo_virtualFolder = Virtual Folder ResourceInfo_unknown = Unknown @@ -642,6 +644,7 @@ ResourceInfo_fileNotExist = {0} - (does not exist) ResourceInfo_path = &Path: ResourceInfo_lastModified = Last &modified: +ResourceInfo_folderHierarchy = Folder hierarchy: ResourceInfo_fileEncodingTitle = Default encoding for &text files ResourceInfo_fileContentEncodingFormat = &Default (determined from content: {0}) ResourceInfo_fileContainerEncodingFormat = Default (&inherited from container: {0}) Index: src/org/eclipse/ui/internal/ide/dialogs/IDEResourceInfoUtils.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEResourceInfoUtils.java,v retrieving revision 1.24 diff -u -r1.24 IDEResourceInfoUtils.java --- src/org/eclipse/ui/internal/ide/dialogs/IDEResourceInfoUtils.java 5 Mar 2010 16:01:11 -0000 1.24 +++ src/org/eclipse/ui/internal/ide/dialogs/IDEResourceInfoUtils.java 9 Sep 2010 19:46:44 -0000 @@ -60,6 +60,8 @@ private static String FOLDER_LABEL = IDEWorkbenchMessages.ResourceInfo_folder; private static String LINKED_FILE_LABEL = IDEWorkbenchMessages.ResourceInfo_linkedFile; + + private static String FLOATING_FILE_LABEL = IDEWorkbenchMessages.ResourceInfo_floatingFile; private static String LINKED_FOLDER_LABEL = IDEWorkbenchMessages.ResourceInfo_linkedFolder; @@ -351,6 +353,9 @@ IContentDescription description) { if (resource.getType() == IResource.FILE) { + if (resource.isFloating()) { + return FLOATING_FILE_LABEL; + } if (resource.isLinked()) { return LINKED_FILE_LABEL; } Index: src/org/eclipse/ui/internal/ide/dialogs/ResourceInfoPage.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/ResourceInfoPage.java,v retrieving revision 1.48 diff -u -r1.48 ResourceInfoPage.java --- src/org/eclipse/ui/internal/ide/dialogs/ResourceInfoPage.java 10 May 2010 14:01:35 -0000 1.48 +++ src/org/eclipse/ui/internal/ide/dialogs/ResourceInfoPage.java 9 Sep 2010 19:46:45 -0000 @@ -67,6 +67,8 @@ */ public class ResourceInfoPage extends PropertyPage { + private Button flattenBox; + private Button editableBox; private Button executableBox; @@ -86,6 +88,8 @@ private boolean previousArchiveValue; private boolean previousDerivedValue; + + private boolean previousFlattenValue; private int previousPermissionsValue; @@ -104,7 +108,7 @@ private static String ARCHIVE = IDEWorkbenchMessages.ResourceInfo_archive; private static String DERIVED = IDEWorkbenchMessages.ResourceInfo_derived; - + private static String TYPE_TITLE = IDEWorkbenchMessages.ResourceInfo_type; private static String LOCATION_TITLE = IDEWorkbenchMessages.ResourceInfo_location; @@ -116,6 +120,10 @@ private static String PATH_TITLE = IDEWorkbenchMessages.ResourceInfo_path; private static String TIMESTAMP_TITLE = IDEWorkbenchMessages.ResourceInfo_lastModified; + + private static String FOLDER_HIERARCHY_TITLE = IDEWorkbenchMessages.ResourceInfo_folderHierarchy; + + private static String FLATTEN = IDEWorkbenchMessages.ResourceInfo_flatten; private static String FILE_ENCODING_TITLE = IDEWorkbenchMessages.WorkbenchPreference_encoding; @@ -196,7 +204,7 @@ Composite locationComposite = new Composite(basicInfoComposite, SWT.NULL); layout = new GridLayout(); - layout.numColumns = 2; + layout.numColumns = resource.isFloating() ? 1:2; layout.marginWidth = 0; layout.marginHeight = 0; locationComposite.setLayout(layout); @@ -221,24 +229,26 @@ locationValue.setBackground(locationValue.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); - Button editButton = new Button(locationComposite, SWT.PUSH); - editButton.setText(EDIT_TITLE); - setButtonLayoutData(editButton); - ((GridData) editButton.getLayoutData()).verticalAlignment = SWT.TOP; - int locationValueHeight = locationValue.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y; - int editButtonHeight = editButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y; - int verticalIndent = (editButtonHeight - locationValueHeight) / 2 ; - ((GridData) locationTitle.getLayoutData()).verticalIndent = verticalIndent; - ((GridData) locationValue.getLayoutData()).verticalIndent = verticalIndent; - editButton.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - editLinkLocation(); - } - - public void widgetSelected(SelectionEvent e) { - editLinkLocation(); - } - }); + if (!resource.isFloating()) { + Button editButton = new Button(locationComposite, SWT.PUSH); + editButton.setText(EDIT_TITLE); + setButtonLayoutData(editButton); + ((GridData) editButton.getLayoutData()).verticalAlignment = SWT.TOP; + int locationValueHeight = locationValue.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y; + int editButtonHeight = editButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y; + int verticalIndent = (editButtonHeight - locationValueHeight) / 2 ; + ((GridData) locationTitle.getLayoutData()).verticalIndent = verticalIndent; + ((GridData) locationValue.getLayoutData()).verticalIndent = verticalIndent; + editButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + editLinkLocation(); + } + + public void widgetSelected(SelectionEvent e) { + editLinkLocation(); + } + }); + } // displayed in all cases since the link can be changed to a path variable any time by the user in this dialog Label resolvedLocationTitle = new Label(basicInfoComposite, @@ -311,6 +321,18 @@ timeStampValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + if (resource instanceof IContainer) + { + Label folderHierarchyLabel = new Label(basicInfoComposite, SWT.NONE); + folderHierarchyLabel.setText(FOLDER_HIERARCHY_TITLE); + + flattenBox = new Button(basicInfoComposite, SWT.CHECK | SWT.RIGHT); + flattenBox.setAlignment(SWT.LEFT); + flattenBox.setText(FLATTEN); + previousFlattenValue = ((IContainer) resource).isFlatten(); + flattenBox.setSelection(previousFlattenValue); + } + return basicInfoComposite; } @@ -899,6 +921,10 @@ this.derivedBox.setSelection(false); } + if (this.flattenBox != null) { + this.flattenBox.setSelection(false); + } + if (permissionBoxes != null) { int defaultPermissionValues = getDefaulPermissions(resource.getType() == IResource.FOLDER); setPermissionsSelection(defaultPermissionValues); @@ -1000,6 +1026,15 @@ derivedBox.setSelection(isDerived); } } + if (this.flattenBox != null) { + boolean localFlattenValue = flattenBox.getSelection(); + if (previousFlattenValue != localFlattenValue) { + ((IContainer)resource).setFlatten(localFlattenValue, 0, null); + boolean isFlatten = ((IContainer)resource).isFlatten(); + previousFlattenValue = isFlatten; + flattenBox.setSelection(isFlatten); + } + } } catch (CoreException exception) { ErrorDialog.openError(getShell(), IDEWorkbenchMessages.InternalError, exception