/******************************************************************************* * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Mathias Kinzler (SAP AG) - improve UI responsiveness *******************************************************************************/ package org.eclipse.egit.ui.internal.dialogs; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jgit.lib.Repository; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE.SharedImages; /** * Builds the nodes for a file tree * */ public class FileTreeContentProvider implements ITreeContentProvider { private final Repository repository; private final List<Node> rootNodes = new ArrayList<>(); private List<String> input; private Mode mode = Mode.REPO_RELATIVE_PATHS; private List<IPath> projectPaths; private Image folderImage = PlatformUI.getWorkbench().getSharedImages() .getImage(ISharedImages.IMG_OBJ_FOLDER); private Image fileImage = PlatformUI.getWorkbench().getSharedImages() .getImage(ISharedImages.IMG_OBJ_FILE); private Image projectImage = PlatformUI.getWorkbench().getSharedImages() .getImage(SharedImages.IMG_OBJ_PROJECT); /** * Describe how to show the paths * */ public enum Mode { /** * The paths are shown relative to the repository (default) */ REPO_RELATIVE_PATHS, /** * The paths are shown as full file system paths */ FULL_PATHS, /** * The paths are shown as resource paths (relative to the workspace) */ RESOURCE_PATHS; } /** * The node */ public abstract class Node { private final String myName; private final Node myParent; /** * Child list */ protected final List<Node> myChildren = new ArrayList<>(); Node(Node parent, String name) { myParent = parent; myName = name; if (parent != null) parent.addChild(this); } /** * @return a boolean */ public abstract boolean hasChildren(); /** * @return an image */ public abstract Image getImage(); /** * @return the name */ public String getName() { return myName; } /** * @return the parent */ public Node getParent() { return myParent; } private void addChild(Node child) { myChildren.add(child); } /** * @return the children or null */ public List<Node> getChildren() { if (myChildren != null) return myChildren; return null; } @Override public String toString() { return myName; } } private class FolderNode extends Node { FolderNode(Node parent, String name) { super(parent, name); } @Override public boolean hasChildren() { return true; } @Override public Image getImage() { if (mode == Mode.RESOURCE_PATHS && getParent() instanceof VirtualNode) return projectImage; return folderImage; } } private class NoResourceNode extends Node { NoResourceNode(Node parent, String name) { super(parent, name); } @Override public boolean hasChildren() { return true; } @Override public Image getImage() { return folderImage; } } class FileNode extends Node { FileNode(Node parent, String name) { super(parent, name); } @Override public boolean hasChildren() { return false; } @Override public Image getImage() { return fileImage; } } private class VirtualNode extends FolderNode { VirtualNode() { super(null, ""); //$NON-NLS-1$ } @Override public boolean hasChildren() { return !myChildren.isEmpty(); } } /** * @param repository */ public FileTreeContentProvider(Repository repository) { this.repository = repository; } /** * @param mode */ public void setMode(Mode mode) { this.mode = mode; } @Override public Object[] getChildren(Object parent) { return ((Node) parent).getChildren().toArray(); } @Override public Object getParent(Object child) { return ((Node) child).getParent(); } @Override public boolean hasChildren(Object parent) { return ((Node) parent).hasChildren(); } @Override public Object[] getElements(Object arg0) { return rootNodes.toArray(); } @Override public void dispose() { // nothing to dispose } @Override @SuppressWarnings("unchecked") public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { rootNodes.clear(); input = (List<String>) newInput; if (input == null) return; VirtualNode virtualNode = new VirtualNode(); Node parentNode = virtualNode; NoResourceNode noResourceNode = null; IPath repositoryRoot = new Path(repository.getWorkTree() .getAbsolutePath()); for (String pathString : input) { IPath path; if (mode == Mode.FULL_PATHS) path = repositoryRoot.append(pathString); else if (mode == Mode.RESOURCE_PATHS) path = resolveResourcePath(repositoryRoot.append(pathString)); else path = new Path(pathString); if (path == null) { path = repositoryRoot.append(pathString); if (noResourceNode == null) { noResourceNode = new NoResourceNode( virtualNode, UIText.FileTreeContentProvider_NonWorkspaceResourcesNode); } parentNode = noResourceNode; } else parentNode = virtualNode; for (int i = 0; i < path.segmentCount(); i++) { String segment = path.segment(i); Node foundNode = null; for (Node node : parentNode.getChildren()) { if (node.getName().equals(segment) && !(node instanceof FileNode)) { foundNode = node; break; } } if (foundNode == null) { if (i < path.segmentCount() - 1) parentNode = new FolderNode(parentNode, segment); else new FileNode(parentNode, segment); } else { parentNode = foundNode; } } } rootNodes.addAll(virtualNode.getChildren()); } private IPath resolveResourcePath(IPath fullPath) { for (IPath projectPath : getProjectPaths()) { if (projectPath.isPrefixOf(fullPath)) { return fullPath .removeFirstSegments(projectPath.segmentCount() - 1); } } return null; } private List<IPath> getProjectPaths() { if (projectPaths == null) { projectPaths = new ArrayList<>(); for (IProject project : ResourcesPlugin.getWorkspace().getRoot() .getProjects()) { RepositoryMapping mapping = RepositoryMapping .getMapping(project); if (mapping != null && mapping.getRepository().equals(repository)) { projectPaths.add(project.getLocation()); } } } return projectPaths; } }