summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorStephen Elsemore2013-06-27 16:19:28 (EDT)
committer Matthias Sohn2013-08-10 20:30:41 (EDT)
commit1ef79b6d9abed44ee7facf4c665f608d85cb67cd (patch)
tree9d1b321ecc8d7f81b53b5564be6aafafc9b6e457
parent94fb639496f53183ebda495a01b61d663f453de8 (diff)
downloadegit-1ef79b6d9abed44ee7facf4c665f608d85cb67cd.zip
egit-1ef79b6d9abed44ee7facf4c665f608d85cb67cd.tar.gz
egit-1ef79b6d9abed44ee7facf4c665f608d85cb67cd.tar.bz2
[stagingView] Add presentation options (list, tree, compact tree)refs/changes/76/12676/18
This adds different options for presenting the unstaged and staged files in the staging view. "List" is the same as before, just a flat list of files, e.g. file1 - src/org/eclipse file2 - src/org/eclipse "Tree" shows the files in a full folder tree, e.g. * src * org * eclipse * file1 * file2 "Compact Tree" shows the files in a folder tree where folders that have just one subfolder do not result in a node, e.g. * src/org/eclipse * file1 * file2 When an expanded node is dragged from one tree to another (stage/unstage), the expanded state should be preserved. CQ: 7377 Bug: 407607 Also-by: Robin Stocker <robin@nibor.org> Change-Id: I6509f2ee0f63fccf0391418cc3d41223e71c41de Signed-off-by: Stephen Elsemore <selsemore@collab.net> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Robin Stocker <robin@nibor.org>
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ResourceUtil.java23
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/compactLayout.gifbin0 -> 355 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/flatLayout.gifbin0 -> 97 bytes
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java8
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java12
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java34
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingFolderEntry.java125
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java764
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java260
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java107
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties4
13 files changed, 1089 insertions, 253 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ResourceUtil.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ResourceUtil.java
index 0d362ee..775d1a8 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ResourceUtil.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ResourceUtil.java
@@ -58,8 +58,7 @@ public class ResourceUtil {
IFile file = getFileForLocationURI(root, uri);
if (file != null)
return file;
- IContainer[] containers = root.findContainersForLocationURI(uri);
- return getExistingResourceWithShortestPath(containers);
+ return getContainerForLocationURI(root, uri);
}
/**
@@ -77,6 +76,20 @@ public class ResourceUtil {
}
/**
+ * Return the corresponding container if it exists.
+ * <p>
+ * The returned container will be relative to the most nested non-closed project.
+ *
+ * @param location
+ * @return the container, or null
+ */
+ public static IContainer getContainerForLocation(IPath location) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ URI uri = URIUtil.toURI(location);
+ return getContainerForLocationURI(root, uri);
+ }
+
+ /**
* Get the {@link IFile} corresponding to the arguments if it exists.
* <p>
* The returned file will be relative to the most nested non-closed project.
@@ -160,6 +173,12 @@ public class ResourceUtil {
return getExistingResourceWithShortestPath(files);
}
+ private static IContainer getContainerForLocationURI(IWorkspaceRoot root,
+ URI uri) {
+ IContainer[] containers = root.findContainersForLocationURI(uri);
+ return getExistingResourceWithShortestPath(containers);
+ }
+
private static <T extends IResource> T getExistingResourceWithShortestPath(
T[] resources) {
int shortestPathSegmentCount = Integer.MAX_VALUE;
diff --git a/org.eclipse.egit.ui/icons/elcl16/compactLayout.gif b/org.eclipse.egit.ui/icons/elcl16/compactLayout.gif
new file mode 100644
index 0000000..45b1ea5
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/compactLayout.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/flatLayout.gif b/org.eclipse.egit.ui/icons/elcl16/flatLayout.gif
new file mode 100644
index 0000000..bdef879
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/flatLayout.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
index fa98d05..4b11dfc 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
@@ -16,6 +16,7 @@ import java.io.File;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator;
+import org.eclipse.egit.ui.internal.staging.StagingView;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jgit.util.FS;
@@ -95,6 +96,8 @@ public class PluginPreferenceInitializer extends AbstractPreferenceInitializer {
store.setDefault(UIPreferences.HISTORY_SHOW_TAG_SEQUENCE, false);
store.setDefault(UIPreferences.BLAME_IGNORE_WHITESPACE, false);
store.setDefault(UIPreferences.REMOTE_CONNECTION_TIMEOUT, 30 /* seconds */);
+ store.setDefault(UIPreferences.STAGING_VIEW_PRESENTATION,
+ StagingView.Presentation.LIST.name());
store.setDefault(UIPreferences.STAGING_VIEW_FILENAME_MODE, true);
store.setDefault(UIPreferences.CLONE_WIZARD_STORE_SECURESTORE, false);
store.setDefault(UIPreferences.COMMIT_DIALOG_HISTORY_SIZE, 10);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
index 4f195c6..92a322b 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
@@ -190,6 +190,8 @@ public class UIPreferences {
/** */
public static final String STAGING_VIEW_FILENAME_MODE = "StagingView_FileNameMode"; //$NON-NLS-1$
/** */
+ public static final String STAGING_VIEW_PRESENTATION = "StagingView_Presentation"; //$NON-NLS-1$
+ /** */
public static final String PAGE_COMMIT_PREFERENCES = "org.eclipse.egit.ui.internal.preferences.CommitDialogPreferencePage"; //$NON-NLS-1$
/** */
public static final String BLAME_IGNORE_WHITESPACE = "Blame_IgnoreWhitespace"; //$NON-NLS-1$
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java
index 99bf8fd..00d6f35 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java
@@ -231,6 +231,12 @@ public class UIIcons {
/** Hierarchy layout icon */
public final static ImageDescriptor HIERARCHY;
+ /** Flat presentation icon */
+ public final static ImageDescriptor FLAT;
+
+ /** Compact tree presentation icon */
+ public final static ImageDescriptor COMPACT;
+
/** base URL */
public final static URL base;
@@ -312,6 +318,8 @@ public class UIIcons {
CLEAN = map("obj16/clean_obj.gif"); //$NON-NLS-1$
STASH = map("obj16/stash.png"); //$NON-NLS-1$
HIERARCHY = map("elcl16/hierarchicalLayout.gif"); //$NON-NLS-1$
+ FLAT = map("elcl16/flatLayout.gif"); //$NON-NLS-1$
+ COMPACT = map("elcl16/compactLayout.gif"); //$NON-NLS-1$
}
private static ImageDescriptor map(final String icon) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
index 9f31a1e..fe1c0f4 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java
@@ -4669,6 +4669,18 @@ public class UIText extends NLS {
public static String StagingView_DeleteItemMenuLabel;
/** */
+ public static String StagingView_Presentation;
+
+ /** */
+ public static String StagingView_List;
+
+ /** */
+ public static String StagingView_Tree;
+
+ /** */
+ public static String StagingView_CompactTree;
+
+ /** */
public static String StagingView_Find;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
index 99f8641..2b2e916 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
@@ -30,6 +30,9 @@ import org.eclipse.jgit.lib.Repository;
* A staged/unstaged entry in the table
*/
public class StagingEntry implements IAdaptable, IProblemDecoratable, IDecoratableResource {
+ private String name;
+ private StagingFolderEntry parent;
+
/**
* State of the node
*/
@@ -125,13 +128,20 @@ public class StagingEntry implements IAdaptable, IProblemDecoratable, IDecoratab
}
/**
- * @return the full path for this node
+ * @return the repo-relative path for this file
*/
public String getPath() {
return path;
}
/**
+ * @return the repo-relative path of the parent
+ */
+ public IPath getParentPath() {
+ return new Path(path).removeLastSegments(1);
+ }
+
+ /**
* @return the repository for this node
*/
public Repository getRepository() {
@@ -167,6 +177,21 @@ public class StagingEntry implements IAdaptable, IProblemDecoratable, IDecoratab
return absolutePath;
}
+ /**
+ * @return parent StagingFolderEntry
+ */
+ public StagingFolderEntry getParent() {
+ return parent;
+ }
+
+ /**
+ * @param parent
+ * StagingFolderEntry
+ */
+ public void setParent(StagingFolderEntry parent) {
+ this.parent = parent;
+ }
+
public int getProblemSeverity() {
IFile file = getFile();
if (file == null)
@@ -192,8 +217,11 @@ public class StagingEntry implements IAdaptable, IProblemDecoratable, IDecoratab
}
public String getName() {
- // Not used in StagingViewLabelProvider
- return null;
+ if (name == null) {
+ IPath parsed = Path.fromOSString(getPath());
+ name = parsed.lastSegment();
+ }
+ return name;
}
public String getRepositoryName() {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingFolderEntry.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingFolderEntry.java
new file mode 100644
index 0000000..1f6dd43
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingFolderEntry.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (C) 2013, Stephen Elsemore <selsemore@collab.net> and others.
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.staging;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.egit.core.internal.util.ResourceUtil;
+import org.eclipse.egit.ui.internal.decorators.IProblemDecoratable;
+
+/**
+ * A staged/unstaged folder entry in the tree
+ */
+public class StagingFolderEntry implements IAdaptable, IProblemDecoratable {
+ private final IPath repoLocation;
+ private final IPath repoRelativePath;
+ private final IPath nodePath;
+
+ private StagingFolderEntry parent;
+
+ /**
+ * @param repoLocation
+ * @param repoRelativePath
+ * @param nodePath
+ */
+ public StagingFolderEntry(IPath repoLocation, IPath repoRelativePath,
+ IPath nodePath) {
+ this.repoLocation = repoLocation;
+ this.repoRelativePath = repoRelativePath;
+ this.nodePath = nodePath;
+ }
+
+ /**
+ * @return the container corresponding to the entry, if it exists in the
+ * workspace, null otherwise.
+ */
+ public IContainer getContainer() {
+ return ResourceUtil.getContainerForLocation(getLocation());
+ }
+
+ public int getProblemSeverity() {
+ IContainer container = getContainer();
+ if (container == null)
+ return SEVERITY_NONE;
+
+ try {
+ return container.findMaxProblemSeverity(IMarker.PROBLEM, true,
+ IResource.DEPTH_ONE);
+ } catch (CoreException e) {
+ return SEVERITY_NONE;
+ }
+ }
+
+ public Object getAdapter(Class adapter) {
+ if (adapter == IResource.class || adapter == IContainer.class)
+ return getContainer();
+ else if (adapter == IPath.class)
+ return getLocation();
+ return null;
+ }
+
+ /**
+ * @return the repo-relative path of this folder
+ */
+ public IPath getPath() {
+ return repoRelativePath;
+ }
+
+ /**
+ * @return the absolute path corresponding to the folder entry
+ */
+ public IPath getLocation() {
+ return repoLocation.append(repoRelativePath);
+ }
+
+ /**
+ * @return the repo-relative path of the parent folder entry
+ */
+ public IPath getParentPath() {
+ return repoRelativePath.removeLastSegments(nodePath.segmentCount());
+ }
+
+ /**
+ * @return the path of the node, relative to its parent
+ */
+ public IPath getNodePath() {
+ return nodePath;
+ }
+
+ /**
+ * @return the parent folder entry
+ */
+ public StagingFolderEntry getParent() {
+ return parent;
+ }
+
+ /**
+ * @param parent
+ */
+ public void setParent(StagingFolderEntry parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof StagingFolderEntry)
+ return ((StagingFolderEntry) obj).getLocation().equals(getLocation());
+ return super.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return getLocation().hashCode();
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
index c1122d7..9f5fe86 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java
@@ -18,12 +18,14 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -83,17 +85,17 @@ import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ContentViewer;
-import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
-import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
-import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jgit.api.AddCommand;
@@ -135,15 +137,16 @@ import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
@@ -192,9 +195,9 @@ public class StagingView extends ViewPart implements IShowInSource {
private Section commitMessageSection;
- private TableViewer stagedTableViewer;
+ private TreeViewer stagedViewer;
- private TableViewer unstagedTableViewer;
+ private TreeViewer unstagedViewer;
private ToggleableWarningLabel warningLabel;
@@ -212,8 +215,47 @@ public class StagingView extends ViewPart implements IShowInSource {
private ISelectionListener selectionChangedListener;
+ private ToolBarManager unstagedToolBarManager;
+
+ private ToolBarManager stagedToolBarManager;
+
+ private Action listPresentationAction;
+
+ private Action treePresentationAction;
+
+ private Action compactTreePresentationAction;
+
+ private Action unstagedExpandAllAction;
+
+ private Action unstagedCollapseAllAction;
+
+ private Action stagedExpandAllAction;
+
+ private Action stagedCollapseAllAction;
+
private Repository currentRepository;
+ private Presentation presentation = Presentation.LIST;
+
+ private Set<IPath> pathsToExpandInStaged = new HashSet<IPath>();
+
+ private Set<IPath> pathsToExpandInUnstaged = new HashSet<IPath>();
+
+ /**
+ * Presentation mode of the staged/unstaged files.
+ */
+ public enum Presentation {
+ /** Show files in flat list */
+ LIST,
+ /** Show folder structure in full tree */
+ TREE,
+ /**
+ * Show folder structure in compact tree (folders with only one child
+ * are folded into parent)
+ */
+ COMPACT_TREE;
+ }
+
static class StagingViewUpdate {
Repository repository;
IndexDiffData indexDiff;
@@ -276,6 +318,34 @@ public class StagingView extends ViewPart implements IShowInSource {
}
}
+ class TreeDecoratingLabelProvider extends DecoratingLabelProvider {
+
+ ILabelProvider provider;
+
+ ILabelDecorator decorator;
+
+ public TreeDecoratingLabelProvider(ILabelProvider provider,
+ ILabelDecorator decorator) {
+ super(provider, decorator);
+ this.provider = provider;
+ this.decorator = decorator;
+ }
+
+ public Image getColumnImage(Object element) {
+ Image image = provider.getImage(element);
+ if (image != null && decorator != null) {
+ Image decorated = decorator.decorateImage(image, element);
+ if (decorated != null)
+ return decorated;
+ }
+ return image;
+ }
+
+ public String getText(Object element) {
+ return provider.getText(element);
+ }
+ }
+
static class StagingViewSearchThread extends Thread {
private StagingView stagingView;
@@ -386,29 +456,30 @@ public class StagingView extends ViewPart implements IShowInSource {
unstagedSection = toolkit.createSection(stagingSashForm,
ExpandableComposite.TITLE_BAR);
- Composite unstagedTableComposite = toolkit
+ createUnstagedToolBarComposite();
+
+ Composite unstagedComposite = toolkit
.createComposite(unstagedSection);
- toolkit.paintBordersFor(unstagedTableComposite);
- unstagedSection.setClient(unstagedTableComposite);
+ toolkit.paintBordersFor(unstagedComposite);
+ unstagedSection.setClient(unstagedComposite);
GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
- .applyTo(unstagedTableComposite);
+ .applyTo(unstagedComposite);
- unstagedTableViewer = new TableViewer(toolkit.createTable(
- unstagedTableComposite, SWT.FULL_SELECTION | SWT.MULTI));
+ unstagedViewer = createTree(unstagedComposite);
GridDataFactory.fillDefaults().grab(true, true)
- .applyTo(unstagedTableViewer.getControl());
- unstagedTableViewer.getTable().setData(FormToolkit.KEY_DRAW_BORDER,
+ .applyTo(unstagedViewer.getControl());
+ unstagedViewer.getTree().setData(FormToolkit.KEY_DRAW_BORDER,
FormToolkit.TREE_BORDER);
- unstagedTableViewer.getTable().setLinesVisible(true);
- unstagedTableViewer.setLabelProvider(createLabelProvider(unstagedTableViewer));
- unstagedTableViewer.setContentProvider(new StagingViewContentProvider(
+ unstagedViewer.getTree().setLinesVisible(true);
+ unstagedViewer.setLabelProvider(createLabelProvider(unstagedViewer));
+ unstagedViewer.setContentProvider(new StagingViewContentProvider(this,
true));
- unstagedTableViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY
+ unstagedViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY
| DND.DROP_LINK,
new Transfer[] { LocalSelectionTransfer.getTransfer(),
FileTransfer.getInstance() }, new StagingDragListener(
- unstagedTableViewer));
- unstagedTableViewer.addDropSupport(DND.DROP_MOVE,
+ unstagedViewer));
+ unstagedViewer.addDropSupport(DND.DROP_MOVE,
new Transfer[] { LocalSelectionTransfer.getTransfer() },
new DropTargetAdapter() {
public void drop(DropTargetEvent event) {
@@ -419,8 +490,7 @@ public class StagingView extends ViewPart implements IShowInSource {
event.detail = DND.DROP_COPY;
if (event.data instanceof IStructuredSelection) {
final IStructuredSelection selection = (IStructuredSelection) event.data;
- if (selection.getFirstElement() instanceof StagingEntry)
- unstage(selection);
+ unstage(selection);
}
}
@@ -428,7 +498,7 @@ public class StagingView extends ViewPart implements IShowInSource {
event.detail = DND.DROP_MOVE;
}
});
- unstagedTableViewer.addOpenListener(new IOpenListener() {
+ unstagedViewer.addOpenListener(new IOpenListener() {
public void open(OpenEvent event) {
compareWith(event);
}
@@ -441,14 +511,7 @@ public class StagingView extends ViewPart implements IShowInSource {
Composite commitMessageToolbarComposite = toolkit
.createComposite(commitMessageSection);
commitMessageToolbarComposite.setBackground(null);
- RowLayout commitMessageRowLayout = new RowLayout();
- commitMessageRowLayout.marginHeight = 0;
- commitMessageRowLayout.marginWidth = 0;
- commitMessageRowLayout.marginTop = 0;
- commitMessageRowLayout.marginBottom = 0;
- commitMessageRowLayout.marginLeft = 0;
- commitMessageRowLayout.marginRight = 0;
- commitMessageToolbarComposite.setLayout(commitMessageRowLayout);
+ commitMessageToolbarComposite.setLayout(createRowLayoutWithoutMargin());
commitMessageSection.setTextClient(commitMessageToolbarComposite);
ToolBarManager commitMessageToolBarManager = new ToolBarManager(
SWT.FLAT | SWT.HORIZONTAL);
@@ -597,28 +660,30 @@ public class StagingView extends ViewPart implements IShowInSource {
stagedSection = toolkit.createSection(stagingSashForm,
ExpandableComposite.TITLE_BAR);
- Composite stagedTableComposite = toolkit.createComposite(stagedSection);
- toolkit.paintBordersFor(stagedTableComposite);
- stagedSection.setClient(stagedTableComposite);
+
+ createStagedToolBarComposite();
+
+ Composite stagedComposite = toolkit.createComposite(stagedSection);
+ toolkit.paintBordersFor(stagedComposite);
+ stagedSection.setClient(stagedComposite);
GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
- .applyTo(stagedTableComposite);
+ .applyTo(stagedComposite);
- stagedTableViewer = new TableViewer(toolkit.createTable(
- stagedTableComposite, SWT.FULL_SELECTION | SWT.MULTI));
+ stagedViewer = createTree(stagedComposite);
GridDataFactory.fillDefaults().grab(true, true)
- .applyTo(stagedTableViewer.getControl());
- stagedTableViewer.getTable().setData(FormToolkit.KEY_DRAW_BORDER,
+ .applyTo(stagedViewer.getControl());
+ stagedViewer.getTree().setData(FormToolkit.KEY_DRAW_BORDER,
FormToolkit.TREE_BORDER);
- stagedTableViewer.getTable().setLinesVisible(true);
- stagedTableViewer.setLabelProvider(createLabelProvider(stagedTableViewer));
- stagedTableViewer.setContentProvider(new StagingViewContentProvider(
+ stagedViewer.getTree().setLinesVisible(true);
+ stagedViewer.setLabelProvider(createLabelProvider(stagedViewer));
+ stagedViewer.setContentProvider(new StagingViewContentProvider(this,
false));
- stagedTableViewer.addDragSupport(
+ stagedViewer.addDragSupport(
DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK,
new Transfer[] { LocalSelectionTransfer.getTransfer(),
FileTransfer.getInstance() }, new StagingDragListener(
- stagedTableViewer));
- stagedTableViewer.addDropSupport(DND.DROP_MOVE,
+ stagedViewer));
+ stagedViewer.addDropSupport(DND.DROP_MOVE,
new Transfer[] { LocalSelectionTransfer.getTransfer() },
new DropTargetAdapter() {
public void drop(DropTargetEvent event) {
@@ -644,7 +709,7 @@ public class StagingView extends ViewPart implements IShowInSource {
event.detail = DND.DROP_MOVE;
}
});
- stagedTableViewer.addOpenListener(new IOpenListener() {
+ stagedViewer.addOpenListener(new IOpenListener() {
public void open(OpenEvent event) {
compareWith(event);
}
@@ -682,8 +747,8 @@ public class StagingView extends ViewPart implements IShowInSource {
updateToolbar();
enableCommitWidgets(false);
- createPopupMenu(unstagedTableViewer);
- createPopupMenu(stagedTableViewer);
+ createPopupMenu(unstagedViewer);
+ createPopupMenu(stagedViewer);
final ICommitMessageComponentNotifications listener = new ICommitMessageComponentNotifications() {
@@ -745,41 +810,116 @@ public class StagingView extends ViewPart implements IShowInSource {
selectionChangedListener.selectionChanged(part, selection);
}
- site.setSelectionProvider(unstagedTableViewer);
+ site.setSelectionProvider(unstagedViewer);
ViewerFilter filter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
- if (element instanceof StagingEntry) {
- if (filterText != null && filterText.getText() != null
- && filterText.getText().trim().length() > 0) {
- return ((StagingEntry) element)
- .getPath()
- .toUpperCase()
- .contains(
- filterText.getText().trim()
- .toUpperCase());
- }
- }
+ StagingViewContentProvider contentProvider = getContentProvider((TreeViewer) viewer);
+ if (element instanceof StagingEntry)
+ return contentProvider.isInFilter((StagingEntry) element);
+ else if (element instanceof StagingFolderEntry)
+ return contentProvider
+ .hasVisibleChildren((StagingFolderEntry) element);
return true;
}
};
- unstagedTableViewer.addFilter(filter);
- stagedTableViewer.addFilter(filter);
+ unstagedViewer.addFilter(filter);
+ stagedViewer.addFilter(filter);
+ }
+
+ private void createUnstagedToolBarComposite() {
+ Composite unstagedToolbarComposite = toolkit
+ .createComposite(unstagedSection);
+ unstagedToolbarComposite.setBackground(null);
+ unstagedToolbarComposite.setLayout(createRowLayoutWithoutMargin());
+ unstagedSection.setTextClient(unstagedToolbarComposite);
+ unstagedExpandAllAction = new Action(UIText.UIUtils_ExpandAll,
+ IAction.AS_PUSH_BUTTON) {
+ public void run() {
+ unstagedViewer.expandAll();
+ }
+ };
+ unstagedExpandAllAction.setImageDescriptor(UIIcons.EXPAND_ALL);
+
+ unstagedCollapseAllAction = new Action(UIText.UIUtils_CollapseAll,
+ IAction.AS_PUSH_BUTTON) {
+ public void run() {
+ unstagedViewer.collapseAll();
+ }
+ };
+ unstagedCollapseAllAction.setImageDescriptor(UIIcons.COLLAPSEALL);
+
+ unstagedToolBarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
+
+ unstagedToolBarManager.add(unstagedExpandAllAction);
+ unstagedToolBarManager.add(unstagedCollapseAllAction);
+
+ unstagedToolBarManager.update(true);
+ unstagedToolBarManager.createControl(unstagedToolbarComposite);
+ }
+
+ private void createStagedToolBarComposite() {
+ Composite stagedToolbarComposite = toolkit
+ .createComposite(stagedSection);
+ stagedToolbarComposite.setBackground(null);
+ stagedToolbarComposite.setLayout(createRowLayoutWithoutMargin());
+ stagedSection.setTextClient(stagedToolbarComposite);
+ stagedExpandAllAction = new Action(UIText.UIUtils_ExpandAll,
+ IAction.AS_PUSH_BUTTON) {
+ public void run() {
+ stagedViewer.expandAll();
+ }
+ };
+ stagedExpandAllAction.setImageDescriptor(UIIcons.EXPAND_ALL);
+
+ stagedCollapseAllAction = new Action(UIText.UIUtils_CollapseAll,
+ IAction.AS_PUSH_BUTTON) {
+ public void run() {
+ stagedViewer.collapseAll();
+ }
+ };
+ stagedCollapseAllAction.setImageDescriptor(UIIcons.COLLAPSEALL);
+
+ stagedToolBarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
+
+ stagedToolBarManager.add(stagedExpandAllAction);
+ stagedToolBarManager.add(stagedCollapseAllAction);
+ stagedToolBarManager.update(true);
+ stagedToolBarManager.createControl(stagedToolbarComposite);
+ }
+
+ private static RowLayout createRowLayoutWithoutMargin() {
+ RowLayout layout = new RowLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.marginTop = 0;
+ layout.marginBottom = 0;
+ layout.marginLeft = 0;
+ layout.marginRight = 0;
+ return layout;
+ }
+
+ /**
+ * @return selected repository
+ */
+ public Repository getCurrentRepository() {
+ return currentRepository;
}
public ShowInContext getShowInContext() {
- if (stagedTableViewer != null && stagedTableViewer.getTable().isFocusControl())
- return getShowInContext(stagedTableViewer);
- else if (unstagedTableViewer != null && unstagedTableViewer.getTable().isFocusControl())
- return getShowInContext(unstagedTableViewer);
+ if (stagedViewer != null && stagedViewer.getTree().isFocusControl())
+ return getShowInContext(stagedViewer);
+ else if (unstagedViewer != null
+ && unstagedViewer.getTree().isFocusControl())
+ return getShowInContext(unstagedViewer);
else
return null;
}
- private ShowInContext getShowInContext(TableViewer tableViewer) {
- IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
+ private ShowInContext getShowInContext(TreeViewer treeViewer) {
+ IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
List<Object> elements = new ArrayList<Object>();
for (Object selectedElement : selection.toList()) {
if (selectedElement instanceof StagingEntry) {
@@ -789,6 +929,13 @@ public class StagingView extends ViewPart implements IShowInSource {
elements.add(file);
else
elements.add(entry.getLocation());
+ } else if (selectedElement instanceof StagingFolderEntry) {
+ StagingFolderEntry entry = (StagingFolderEntry) selectedElement;
+ IContainer container = entry.getContainer();
+ if (container != null)
+ elements.add(container);
+ else
+ elements.add(entry.getLocation());
}
}
return new ShowInContext(null, new StructuredSelection(elements));
@@ -920,10 +1067,9 @@ public class StagingView extends ViewPart implements IShowInSource {
public void run() {
final boolean enable = isChecked();
- getLabelProvider(stagedTableViewer).setFileNameMode(enable);
- getLabelProvider(unstagedTableViewer).setFileNameMode(enable);
- stagedTableViewer.refresh();
- unstagedTableViewer.refresh();
+ getLabelProvider(stagedViewer).setFileNameMode(enable);
+ getLabelProvider(unstagedViewer).setFileNameMode(enable);
+ refreshViewers();
getPreferenceStore().setValue(
UIPreferences.STAGING_VIEW_FILENAME_MODE, enable);
}
@@ -932,6 +1078,81 @@ public class StagingView extends ViewPart implements IShowInSource {
UIPreferences.STAGING_VIEW_FILENAME_MODE));
IMenuManager dropdownMenu = actionBars.getMenuManager();
+ MenuManager presentationMenu = new MenuManager(
+ UIText.StagingView_Presentation);
+ listPresentationAction = new Action(UIText.StagingView_List,
+ IAction.AS_RADIO_BUTTON) {
+ public void run() {
+ presentation = Presentation.LIST;
+ getPreferenceStore().setValue(
+ UIPreferences.STAGING_VIEW_PRESENTATION,
+ Presentation.LIST.name());
+ treePresentationAction.setChecked(false);
+ compactTreePresentationAction.setChecked(false);
+ setExpandCollapseActionsVisible(false);
+ refreshViewers();
+ }
+ };
+ listPresentationAction.setImageDescriptor(UIIcons.FLAT);
+ presentationMenu.add(listPresentationAction);
+
+ treePresentationAction = new Action(UIText.StagingView_Tree,
+ IAction.AS_RADIO_BUTTON) {
+ public void run() {
+ presentation = Presentation.TREE;
+ getPreferenceStore().setValue(
+ UIPreferences.STAGING_VIEW_PRESENTATION,
+ Presentation.TREE.name());
+ listPresentationAction.setChecked(false);
+ compactTreePresentationAction.setChecked(false);
+ setExpandCollapseActionsVisible(true);
+ refreshViewers();
+ }
+ };
+ treePresentationAction.setImageDescriptor(UIIcons.HIERARCHY);
+ presentationMenu.add(treePresentationAction);
+
+ compactTreePresentationAction = new Action(UIText.StagingView_CompactTree,
+ IAction.AS_RADIO_BUTTON) {
+ public void run() {
+ presentation = Presentation.COMPACT_TREE;
+ getPreferenceStore().setValue(
+ UIPreferences.STAGING_VIEW_PRESENTATION,
+ Presentation.COMPACT_TREE.name());
+ listPresentationAction.setChecked(false);
+ treePresentationAction.setChecked(false);
+ setExpandCollapseActionsVisible(true);
+ refreshViewers();
+ }
+ };
+ compactTreePresentationAction.setImageDescriptor(UIIcons.COMPACT);
+ presentationMenu.add(compactTreePresentationAction);
+
+ String presentationString = getPreferenceStore().getString(
+ UIPreferences.STAGING_VIEW_PRESENTATION);
+ if (presentationString.length() > 0) {
+ try {
+ presentation = Presentation.valueOf(presentationString);
+ } catch (IllegalArgumentException e) {
+ // Use already set value of presentation
+ }
+ }
+ switch (presentation) {
+ case LIST:
+ listPresentationAction.setChecked(true);
+ setExpandCollapseActionsVisible(false);
+ break;
+ case TREE:
+ treePresentationAction.setChecked(true);
+ break;
+ case COMPACT_TREE:
+ compactTreePresentationAction.setChecked(true);
+ break;
+ default:
+ break;
+ }
+ dropdownMenu.add(presentationMenu);
+ dropdownMenu.add(new Separator());
dropdownMenu.add(openNewCommitsAction);
dropdownMenu.add(columnLayoutAction);
dropdownMenu.add(fileNameModeAction);
@@ -947,13 +1168,35 @@ public class StagingView extends ViewPart implements IShowInSource {
actionBars.updateActionBars();
}
- private IBaseLabelProvider createLabelProvider(TableViewer tableViewer) {
- StagingViewLabelProvider baseProvider = new StagingViewLabelProvider();
+ private void setExpandCollapseActionsVisible(boolean visible) {
+ for (IContributionItem item : unstagedToolBarManager.getItems())
+ item.setVisible(visible);
+ for (IContributionItem item : stagedToolBarManager.getItems())
+ item.setVisible(visible);
+ unstagedExpandAllAction.setEnabled(visible);
+ unstagedCollapseAllAction.setEnabled(visible);
+ stagedExpandAllAction.setEnabled(visible);
+ stagedCollapseAllAction.setEnabled(visible);
+ unstagedToolBarManager.update(true);
+ stagedToolBarManager.update(true);
+ }
+
+ private TreeViewer createTree(Composite composite) {
+ Tree tree = toolkit.createTree(composite, SWT.FULL_SELECTION
+ | SWT.MULTI);
+ tree.setLinesVisible(true);
+ TreeViewer treeViewer = new TreeViewer(tree);
+ return treeViewer;
+ }
+
+ private IBaseLabelProvider createLabelProvider(TreeViewer treeViewer) {
+ StagingViewLabelProvider baseProvider = new StagingViewLabelProvider(
+ this);
baseProvider.setFileNameMode(getPreferenceStore().getBoolean(
UIPreferences.STAGING_VIEW_FILENAME_MODE));
- ProblemLabelDecorator decorator = new ProblemLabelDecorator(tableViewer);
- return new DecoratingStyledCellLabelProvider(baseProvider, decorator, null);
+ ProblemLabelDecorator decorator = new ProblemLabelDecorator(treeViewer);
+ return new TreeDecoratingLabelProvider(baseProvider, decorator);
}
private IPreferenceStore getPreferenceStore() {
@@ -962,9 +1205,9 @@ public class StagingView extends ViewPart implements IShowInSource {
private StagingViewLabelProvider getLabelProvider(ContentViewer viewer) {
IBaseLabelProvider base = viewer.getLabelProvider();
- IStyledLabelProvider styled = ((DelegatingStyledCellLabelProvider) base)
- .getStyledStringProvider();
- return (StagingViewLabelProvider) styled;
+ ILabelProvider labelProvider = ((TreeDecoratingLabelProvider) base)
+ .getLabelProvider();
+ return (StagingViewLabelProvider) labelProvider;
}
private StagingViewContentProvider getContentProvider(ContentViewer viewer) {
@@ -972,22 +1215,22 @@ public class StagingView extends ViewPart implements IShowInSource {
}
private void updateSectionText() {
- stagedSection.setText(MessageFormat.format(
- UIText.StagingView_StagedChanges,
- getSectionCount(stagedTableViewer)));
+ stagedSection.setText(MessageFormat
+ .format(UIText.StagingView_StagedChanges,
+ getSectionCount(stagedViewer)));
unstagedSection.setText(MessageFormat.format(
UIText.StagingView_UnstagedChanges,
- getSectionCount(unstagedTableViewer)));
+ getSectionCount(unstagedViewer)));
}
- private String getSectionCount(TableViewer viewer) {
- int stagingEntryCount = ((StagingViewContentProvider) viewer
- .getContentProvider()).getStagingEntryCount();
- int itemCount = viewer.getTable().getItemCount();
- if (itemCount == stagingEntryCount)
- return Integer.toString(itemCount);
+ private String getSectionCount(TreeViewer viewer) {
+ StagingViewContentProvider contentProvider = getContentProvider(viewer);
+ int count = contentProvider.getCount();
+ int shownCount = contentProvider.getShownCount();
+ if (shownCount == count)
+ return Integer.toString(count);
else
- return itemCount + "/" + stagingEntryCount; //$NON-NLS-1$
+ return shownCount + "/" + count; //$NON-NLS-1$
}
private void updateMessage() {
@@ -1010,7 +1253,8 @@ public class StagingView extends ViewPart implements IShowInSource {
private void compareWith(OpenEvent event) {
IStructuredSelection selection = (IStructuredSelection) event
.getSelection();
- if (selection.isEmpty())
+ if (selection.isEmpty()
+ || !(selection.getFirstElement() instanceof StagingEntry))
return;
StagingEntry stagingEntry = (StagingEntry) selection.getFirstElement();
if (stagingEntry.isSubmodule())
@@ -1034,36 +1278,58 @@ public class StagingView extends ViewPart implements IShowInSource {
}
}
- private void createPopupMenu(final TableViewer tableViewer) {
+ private void createPopupMenu(final TreeViewer treeViewer) {
final MenuManager menuMgr = new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
- Control control = tableViewer.getControl();
+ Control control = treeViewer.getControl();
control.setMenu(menuMgr.createContextMenu(control));
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
- IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
+ IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
if (selection.isEmpty())
return;
+ List<StagingEntry> stagingEntryList = new ArrayList<StagingEntry>();
+
boolean submoduleSelected = false;
- for (Object item : selection.toArray())
- if (((StagingEntry) item).isSubmodule()) {
- submoduleSelected = true;
- break;
+ boolean folderSelected = false;
+ for (Object element : selection.toArray()) {
+ if (element instanceof StagingFolderEntry) {
+ StagingFolderEntry folder = (StagingFolderEntry) element;
+ folderSelected = true;
+ StagingViewContentProvider contentProvider = getContentProvider(treeViewer);
+ List<StagingEntry> stagingEntries = contentProvider
+ .getStagingEntriesFiltered(folder);
+ for (StagingEntry stagingEntry : stagingEntries) {
+ if (!stagingEntryList.contains(stagingEntry))
+ stagingEntryList.add(stagingEntry);
+ }
+ } else if (element instanceof StagingEntry) {
+ StagingEntry entry = (StagingEntry) element;
+ if (entry.isSubmodule())
+ submoduleSelected = true;
+ if (!stagingEntryList.contains(entry))
+ stagingEntryList.add(entry);
}
+ }
- Action openWorkingTreeVersion = new Action(
- UIText.CommitFileDiffViewer_OpenWorkingTreeVersionInEditorMenuLabel) {
- @Override
- public void run() {
- openSelectionInEditor(tableViewer.getSelection());
- }
- };
- openWorkingTreeVersion.setEnabled(!submoduleSelected);
- menuMgr.add(openWorkingTreeVersion);
+ final IStructuredSelection fileSelection = new StructuredSelection(
+ stagingEntryList);
- Set<StagingEntry.Action> availableActions = getAvailableActions(selection);
+ if (!folderSelected) {
+ Action openWorkingTreeVersion = new Action(
+ UIText.CommitFileDiffViewer_OpenWorkingTreeVersionInEditorMenuLabel) {
+ @Override
+ public void run() {
+ openSelectionInEditor(fileSelection);
+ }
+ };
+ openWorkingTreeVersion.setEnabled(!submoduleSelected);
+ menuMgr.add(openWorkingTreeVersion);
+ }
+
+ Set<StagingEntry.Action> availableActions = getAvailableActions(fileSelection);
boolean addReplaceWithFileInGitIndex = availableActions.contains(StagingEntry.Action.REPLACE_WITH_FILE_IN_GIT_INDEX);
boolean addReplaceWithHeadRevision = availableActions.contains(StagingEntry.Action.REPLACE_WITH_HEAD_REVISION);
@@ -1077,34 +1343,42 @@ public class StagingView extends ViewPart implements IShowInSource {
menuMgr.add(new Action(UIText.StagingView_StageItemMenuLabel) {
@Override
public void run() {
- stage((IStructuredSelection) tableViewer.getSelection());
+ stage(fileSelection);
}
});
if (addUnstage)
menuMgr.add(new Action(UIText.StagingView_UnstageItemMenuLabel) {
@Override
public void run() {
- unstage((IStructuredSelection) tableViewer.getSelection());
+ unstage(fileSelection);
}
});
- boolean selectionIncludesNonWorkspaceResources = selectionIncludesNonWorkspaceResources(tableViewer.getSelection());
+ boolean selectionIncludesNonWorkspaceResources = selectionIncludesNonWorkspaceResources(fileSelection);
if (addReplaceWithFileInGitIndex)
if (selectionIncludesNonWorkspaceResources)
- menuMgr.add(new ReplaceAction(UIText.StagingView_replaceWithFileInGitIndex, selection, false));
+ menuMgr.add(new ReplaceAction(
+ UIText.StagingView_replaceWithFileInGitIndex,
+ fileSelection, false));
else
- menuMgr.add(createItem(ActionCommands.DISCARD_CHANGES_ACTION, tableViewer)); // replace with index
+ menuMgr.add(createItem(
+ ActionCommands.DISCARD_CHANGES_ACTION,
+ fileSelection)); // replace with index
if (addReplaceWithHeadRevision)
if (selectionIncludesNonWorkspaceResources)
- menuMgr.add(new ReplaceAction(UIText.StagingView_replaceWithHeadRevision, selection, true));
+ menuMgr.add(new ReplaceAction(
+ UIText.StagingView_replaceWithHeadRevision,
+ fileSelection, true));
else
- menuMgr.add(createItem(ActionCommands.REPLACE_WITH_HEAD_ACTION, tableViewer));
+ menuMgr.add(createItem(
+ ActionCommands.REPLACE_WITH_HEAD_ACTION,
+ fileSelection));
if (addIgnore)
- menuMgr.add(new IgnoreAction(selection));
+ menuMgr.add(new IgnoreAction(fileSelection));
if (addDelete)
- menuMgr.add(new DeleteAction(selection));
+ menuMgr.add(new DeleteAction(fileSelection));
if (addLaunchMergeTool)
- menuMgr.add(createItem(ActionCommands.MERGE_TOOL_ACTION, tableViewer));
-
+ menuMgr.add(createItem(ActionCommands.MERGE_TOOL_ACTION,
+ fileSelection));
menuMgr.add(new Separator());
menuMgr.add(createShowInMenu());
}
@@ -1113,14 +1387,37 @@ public class StagingView extends ViewPart implements IShowInSource {
}
/**
+ * @return selected presentation
+ */
+ Presentation getPresentation() {
+ return presentation;
+ }
+
+ /**
+ * @return the trimmed string which is the current filter, empty string for
+ * no filter
+ */
+ String getFilterString() {
+ if (filterText != null)
+ return filterText.getText().trim();
+ else
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
* Refresh the unstaged and staged viewers
*/
public void refreshViewers() {
- Display.getDefault().asyncExec(new Runnable() {
+ Display.getDefault().syncExec(new Runnable() {
public void run() {
- unstagedTableViewer.refresh();
- stagedTableViewer.refresh();
+ Object[] unstagedExpanded = unstagedViewer
+ .getExpandedElements();
+ Object[] stagedExpanded = stagedViewer.getExpandedElements();
+ unstagedViewer.refresh();
+ stagedViewer.refresh();
updateSectionText();
+ unstagedViewer.setExpandedElements(unstagedExpanded);
+ stagedViewer.setExpandedElements(stagedExpanded);
}
});
}
@@ -1198,7 +1495,7 @@ public class StagingView extends ViewPart implements IShowInSource {
@Override
public boolean isEnabled() {
- if (!unstagedTableViewer.getTable().isFocusControl())
+ if (!unstagedViewer.getTree().isFocusControl())
return false;
IStructuredSelection selection = getSelection();
@@ -1206,6 +1503,8 @@ public class StagingView extends ViewPart implements IShowInSource {
return false;
for (Object element : selection.toList()) {
+ if (!(element instanceof StagingEntry))
+ return false;
StagingEntry entry = (StagingEntry) element;
if (!entry.getAvailableActions().contains(StagingEntry.Action.DELETE))
return false;
@@ -1215,7 +1514,7 @@ public class StagingView extends ViewPart implements IShowInSource {
}
private IStructuredSelection getSelection() {
- return (IStructuredSelection) unstagedTableViewer.getSelection();
+ return (IStructuredSelection) unstagedViewer.getSelection();
}
}
@@ -1238,8 +1537,11 @@ public class StagingView extends ViewPart implements IShowInSource {
List<String> result = new ArrayList<String>();
Iterator iterator = selection.iterator();
while (iterator.hasNext()) {
- StagingEntry stagingEntry = (StagingEntry) iterator.next();
- result.add(stagingEntry.getPath());
+ Object selectedItem = iterator.next();
+ if (selectedItem instanceof StagingEntry) {
+ StagingEntry stagingEntry = (StagingEntry) selectedItem;
+ result.add(stagingEntry.getPath());
+ }
}
return result.toArray(new String[result.size()]);
}
@@ -1315,7 +1617,8 @@ public class StagingView extends ViewPart implements IShowInSource {
return availableActions;
}
- private CommandContributionItem createItem(String itemAction, final TableViewer tableViewer) {
+ private CommandContributionItem createItem(String itemAction,
+ final ISelection selection) {
IWorkbench workbench = PlatformUI.getWorkbench();
CommandContributionItemParameter itemParam = new CommandContributionItemParameter(
workbench, null, itemAction, STYLE_PUSH);
@@ -1325,7 +1628,7 @@ public class StagingView extends ViewPart implements IShowInSource {
IHandlerService hsr = (IHandlerService) activeWorkbenchWindow
.getService(IHandlerService.class);
IEvaluationContext ctx = hsr.getCurrentState();
- ctx.addVariable(ACTIVE_MENU_SELECTION_NAME, tableViewer.getSelection());
+ ctx.addVariable(ACTIVE_MENU_SELECTION_NAME, selection);
return new CommandContributionItem(itemParam);
}
@@ -1359,31 +1662,26 @@ public class StagingView extends ViewPart implements IShowInSource {
}
private void stage(IStructuredSelection selection) {
+ StagingViewContentProvider contentProvider = getContentProvider(unstagedViewer);
Git git = new Git(currentRepository);
Iterator iterator = selection.iterator();
List<String> addPaths = new ArrayList<String>();
List<String> rmPaths = new ArrayList<String>();
+ resetPathsToExpand();
while (iterator.hasNext()) {
Object element = iterator.next();
if (element instanceof StagingEntry) {
StagingEntry entry = (StagingEntry) element;
- switch (entry.getState()) {
- case ADDED:
- case CHANGED:
- case REMOVED:
- // already staged
- break;
- case CONFLICTING:
- case MODIFIED:
- case PARTIALLY_MODIFIED:
- case UNTRACKED:
- addPaths.add(entry.getPath());
- break;
- case MISSING:
- case MISSING_AND_CHANGED:
- rmPaths.add(entry.getPath());
- break;
- }
+ selectEntryForStaging(entry, addPaths, rmPaths);
+ addPathAndParentPaths(entry.getParentPath(), pathsToExpandInStaged);
+ } else if (element instanceof StagingFolderEntry) {
+ StagingFolderEntry folder = (StagingFolderEntry) element;
+ List<StagingEntry> entries = contentProvider
+ .getStagingEntriesFiltered(folder);
+ for (StagingEntry entry : entries)
+ selectEntryForStaging(entry, addPaths, rmPaths);
+ addExpandedPathsBelowFolder(folder, unstagedViewer,
+ pathsToExpandInStaged);
} else {
IResource resource = AdapterUtils.adapt(element, IResource.class);
if (resource != null) {
@@ -1430,6 +1728,27 @@ public class StagingView extends ViewPart implements IShowInSource {
}
}
+ private void selectEntryForStaging(StagingEntry entry,
+ List<String> addPaths, List<String> rmPaths) {
+ switch (entry.getState()) {
+ case ADDED:
+ case CHANGED:
+ case REMOVED:
+ // already staged
+ break;
+ case CONFLICTING:
+ case MODIFIED:
+ case PARTIALLY_MODIFIED:
+ case UNTRACKED:
+ addPaths.add(entry.getPath());
+ break;
+ case MISSING:
+ case MISSING_AND_CHANGED:
+ rmPaths.add(entry.getPath());
+ break;
+ }
+ }
+
private void unstage(IStructuredSelection selection) {
if (selection.isEmpty())
return;
@@ -1464,7 +1783,7 @@ public class StagingView extends ViewPart implements IShowInSource {
}
try {
- updateDirCache(selection, headRev, edit);
+ processUnstageSelection(selection, headRev, edit);
try {
edit.commit();
@@ -1479,44 +1798,84 @@ public class StagingView extends ViewPart implements IShowInSource {
}
}
- private void updateDirCache(IStructuredSelection selection,
+ private void processUnstageSelection(IStructuredSelection selection,
final RevCommit headRev, final DirCacheEditor edit) {
- Iterator iterator = selection.iterator();
- while (iterator.hasNext()) {
- StagingEntry entry = (StagingEntry) iterator.next();
- switch (entry.getState()) {
- case ADDED:
- edit.add(new DirCacheEditor.DeletePath(entry.getPath()));
- break;
- case CHANGED:
- case REMOVED:
- // set the index object id/file mode back to our head revision
- try {
- final TreeWalk tw = TreeWalk.forPath(currentRepository,
- entry.getPath(), headRev.getTree());
- if (tw != null)
- edit.add(new DirCacheEditor.PathEdit(entry.getPath()) {
- @Override
- public void apply(DirCacheEntry ent) {
- ent.setFileMode(tw.getFileMode(0));
- ent.setObjectId(tw.getObjectId(0));
- // for index & working tree compare
- ent.setLastModified(0);
- }
- });
- } catch (IOException e) {
- // TODO fix text
- MessageDialog.openError(getSite().getShell(),
- UIText.CommitAction_MergeHeadErrorTitle,
- UIText.CommitAction_ErrorReadingMergeMsg);
- }
- break;
- default:
- // unstaged
+ resetPathsToExpand();
+ for (Object element : selection.toList()) {
+ if (element instanceof StagingEntry) {
+ StagingEntry entry = (StagingEntry) element;
+ updateDirCache(headRev, edit, entry);
+ addPathAndParentPaths(entry.getParentPath(), pathsToExpandInUnstaged);
+ } else if (element instanceof StagingFolderEntry) {
+ StagingFolderEntry folder = (StagingFolderEntry) element;
+ List<StagingEntry> entries = getContentProvider(stagedViewer)
+ .getStagingEntriesFiltered(folder);
+ for (StagingEntry entry : entries)
+ updateDirCache(headRev, edit, entry);
+ addExpandedPathsBelowFolder(folder, stagedViewer,
+ pathsToExpandInUnstaged);
}
}
}
+ private void updateDirCache(final RevCommit headRev,
+ final DirCacheEditor edit, final StagingEntry entry) {
+ switch (entry.getState()) {
+ case ADDED:
+ edit.add(new DirCacheEditor.DeletePath(entry.getPath()));
+ break;
+ case CHANGED:
+ case REMOVED:
+ // set the index object id/file mode back to our head revision
+ try {
+ final TreeWalk tw = TreeWalk.forPath(currentRepository,
+ entry.getPath(), headRev.getTree());
+ if (tw != null)
+ edit.add(new DirCacheEditor.PathEdit(entry.getPath()) {
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(tw.getFileMode(0));
+ ent.setObjectId(tw.getObjectId(0));
+ // for index & working tree compare
+ ent.setLastModified(0);
+ }
+ });
+ } catch (IOException e) {
+ // TODO fix text
+ MessageDialog.openError(getSite().getShell(),
+ UIText.CommitAction_MergeHeadErrorTitle,
+ UIText.CommitAction_ErrorReadingMergeMsg);
+ }
+ break;
+ default:
+ // unstaged
+ }
+ }
+
+ private void resetPathsToExpand() {
+ pathsToExpandInStaged = new HashSet<IPath>();
+ pathsToExpandInUnstaged = new HashSet<IPath>();
+ }
+
+ private static void addExpandedPathsBelowFolder(StagingFolderEntry folder,
+ TreeViewer treeViewer, Set<IPath> addToSet) {
+ Object[] expandedElements = treeViewer.getExpandedElements();
+ for (Object expandedElement : expandedElements) {
+ if (expandedElement instanceof StagingFolderEntry) {
+ StagingFolderEntry expandedFolder = (StagingFolderEntry) expandedElement;
+ if (folder.getPath().isPrefixOf(
+ expandedFolder.getPath()))
+ addPathAndParentPaths(expandedFolder.getPath(), addToSet);
+ }
+ }
+ }
+
+ private static void addPathAndParentPaths(IPath initialPath, Set<IPath> addToSet) {
+ for (IPath p = initialPath; p.segmentCount() >= 1; p = p
+ .removeLastSegments(1))
+ addToSet.add(p);
+ }
+
private boolean isValidRepo(final Repository repository) {
return repository != null
&& !repository.isBare()
@@ -1534,8 +1893,8 @@ public class StagingView extends ViewPart implements IShowInSource {
saveCommitMessageComponentState();
currentRepository = null;
StagingViewUpdate update = new StagingViewUpdate(null, null, null);
- unstagedTableViewer.setInput(update);
- stagedTableViewer.setInput(update);
+ unstagedViewer.setInput(update);
+ stagedViewer.setInput(update);
enableCommitWidgets(false);
updateSectionText();
form.setText(UIText.StagingView_NoSelectionTitle);
@@ -1567,9 +1926,21 @@ public class StagingView extends ViewPart implements IShowInSource {
boolean indexDiffAvailable = indexDiff != null;
+ if (repositoryChanged)
+ // Reset paths, they're from the old repository
+ resetPathsToExpand();
+
final StagingViewUpdate update = new StagingViewUpdate(currentRepository, indexDiff, null);
- unstagedTableViewer.setInput(update);
- stagedTableViewer.setInput(update);
+ Object[] unstagedExpanded = unstagedViewer
+ .getExpandedElements();
+ Object[] stagedExpanded = stagedViewer
+ .getExpandedElements();
+ unstagedViewer.setInput(update);
+ stagedViewer.setInput(update);
+ expandPreviousExpandedAndPaths(unstagedExpanded, unstagedViewer,
+ pathsToExpandInUnstaged);
+ expandPreviousExpandedAndPaths(stagedExpanded, stagedViewer,
+ pathsToExpandInStaged);
enableCommitWidgets(indexDiffAvailable);
boolean commitEnabled =
indexDiffAvailable && repository.getRepositoryState().canCommit();
@@ -1596,6 +1967,25 @@ public class StagingView extends ViewPart implements IShowInSource {
return cacheEntry.getIndexDiff();
}
+ private void expandPreviousExpandedAndPaths(Object[] previous,
+ TreeViewer viewer, Set<IPath> additionalPaths) {
+ Set<IPath> paths = new HashSet<IPath>(additionalPaths);
+ // Instead of just expanding the previous elements directly, also expand
+ // all parent paths. This makes it work in case of "re-folding" of
+ // compact tree.
+ for (Object element : previous)
+ if (element instanceof StagingFolderEntry)
+ addPathAndParentPaths(((StagingFolderEntry) element).getPath(), paths);
+ List<Object> expand = new ArrayList<Object>();
+ StagingViewContentProvider stagedContentProvider = getContentProvider(viewer);
+ for (StagingFolderEntry folder : stagedContentProvider
+ .getStagingFolderEntries()) {
+ if (paths.contains(folder.getPath()))
+ expand.add(folder);
+ }
+ viewer.setExpandedElements(expand.toArray());
+ }
+
private void clearCommitMessageToggles() {
amendPreviousCommitAction.setChecked(false);
addChangeIdAction.setChecked(false);
@@ -1750,7 +2140,7 @@ public class StagingView extends ViewPart implements IShowInSource {
}
private Collection<String> getStagedFileNames() {
- StagingViewContentProvider stagedContentProvider = getContentProvider(stagedTableViewer);
+ StagingViewContentProvider stagedContentProvider = getContentProvider(stagedViewer);
StagingEntry[] entries = stagedContentProvider.getStagingEntries();
List<String> files = new ArrayList<String>();
for (StagingEntry entry : entries)
@@ -1795,7 +2185,7 @@ public class StagingView extends ViewPart implements IShowInSource {
}
private boolean isCommitWithoutFilesAllowed() {
- if (stagedTableViewer.getTable().getItemCount() > 0)
+ if (stagedViewer.getTree().getItemCount() > 0)
return true;
if (amendPreviousCommitAction.isChecked())
@@ -1806,7 +2196,7 @@ public class StagingView extends ViewPart implements IShowInSource {
@Override
public void setFocus() {
- unstagedTableViewer.getControl().setFocus();
+ unstagedViewer.getControl().setFocus();
}
@Override
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java
index 25c62b2..dcb7ee9 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewContentProvider.java
@@ -19,46 +19,242 @@ import static org.eclipse.egit.ui.internal.staging.StagingEntry.State.REMOVED;
import static org.eclipse.egit.ui.internal.staging.StagingEntry.State.UNTRACKED;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.staging.StagingView.Presentation;
import org.eclipse.egit.ui.internal.staging.StagingView.StagingViewUpdate;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.submodule.SubmoduleWalk;
+import org.eclipse.ui.model.WorkbenchContentProvider;
/**
- * ContentProvider for staged and unstaged table nodes
+ * ContentProvider for staged and unstaged tree nodes
*/
-public class StagingViewContentProvider implements
- IStructuredContentProvider {
+public class StagingViewContentProvider extends WorkbenchContentProvider {
+ /** All files for the section (staged or unstaged). */
private StagingEntry[] content = new StagingEntry[0];
- private boolean isWorkspace;
- StagingViewContentProvider(boolean workspace) {
- this.isWorkspace = workspace;
+ /** Folders for the "Tree" presentation. */
+ private StagingFolderEntry[] treeFolders;
+
+ /** Folders for the "Compact Tree" presentation. */
+ private StagingFolderEntry[] compactTreeFolders;
+
+ private StagingView stagingView;
+ private boolean unstagedSection;
+
+ private Repository repository;
+
+ StagingViewContentProvider(StagingView stagingView, boolean unstagedSection) {
+ this.stagingView = stagingView;
+ this.unstagedSection = unstagedSection;
+ }
+
+ public Object getParent(Object element) {
+ if (element instanceof StagingFolderEntry)
+ return ((StagingFolderEntry) element).getParent();
+ if (element instanceof StagingEntry)
+ return ((StagingEntry) element).getParent();
+ return null;
+ }
+
+ public boolean hasChildren(Object element) {
+ return !(element instanceof StagingEntry);
}
public Object[] getElements(Object inputElement) {
- return content;
+ return getChildren(inputElement);
}
- StagingEntry[] getStagingEntries() {
- return content;
+ public Object[] getChildren(Object parentElement) {
+ if (repository == null)
+ return new Object[0];
+ if (parentElement instanceof StagingEntry)
+ return new Object[0];
+ if (parentElement instanceof StagingFolderEntry) {
+ return getFolderChildren((StagingFolderEntry) parentElement);
+ } else {
+ if (stagingView.getPresentation() == Presentation.LIST)
+ return content;
+ else {
+ StagingFolderEntry[] allFolders = getStagingFolderEntries();
+ List<Object> roots = new ArrayList<Object>();
+ for (StagingFolderEntry folder : allFolders)
+ if (folder.getParentPath().segmentCount() == 0)
+ roots.add(folder);
+ for (StagingEntry entry : content)
+ if (!entry.getPath().contains("/")) //$NON-NLS-1$
+ roots.add(entry);
+ return roots.toArray(new Object[roots.size()]);
+ }
+ }
+ }
+
+ private Object[] getFolderChildren(StagingFolderEntry parent) {
+ IPath parentPath = parent.getPath();
+ List<Object> children = new ArrayList<Object>();
+ for (StagingFolderEntry folder : getStagingFolderEntries()) {
+ if (folder.getParentPath().equals(parentPath)) {
+ folder.setParent(parent);
+ children.add(folder);
+ }
+ }
+ for (StagingEntry file : content) {
+ if (file.getParentPath().equals(parentPath)) {
+ file.setParent(parent);
+ children.add(file);
+ }
+ }
+ return children.toArray(new Object[children.size()]);
+ }
+
+ StagingFolderEntry[] getStagingFolderEntries() {
+ Presentation presentation = stagingView.getPresentation();
+ switch (presentation) {
+ case COMPACT_TREE:
+ return getCompactTreeFolders();
+ case TREE:
+ return getTreeFolders();
+ default:
+ return new StagingFolderEntry[0];
+ }
+ }
+
+ private StagingFolderEntry[] getCompactTreeFolders() {
+ if (compactTreeFolders == null)
+ compactTreeFolders = calculateTreeFolders(true);
+ return compactTreeFolders;
+ }
+
+ private StagingFolderEntry[] getTreeFolders() {
+ if (treeFolders == null)
+ treeFolders = calculateTreeFolders(false);
+ return treeFolders;
+ }
+
+ private StagingFolderEntry[] calculateTreeFolders(boolean compact) {
+ if (content == null || content.length == 0)
+ return new StagingFolderEntry[0];
+
+ Set<IPath> folderPaths = new HashSet<IPath>();
+ Map<IPath, String> childSegments = new HashMap<IPath, String>();
+
+ for (StagingEntry file : content) {
+ IPath folderPath = file.getParentPath();
+ if (folderPath.segmentCount() == 0)
+ // No folders need to be created
+ continue;
+ folderPaths.add(folderPath);
+ for (IPath p = folderPath; p.segmentCount() != 1; p = p
+ .removeLastSegments(1)) {
+ IPath parent = p.removeLastSegments(1);
+ if (!compact) {
+ folderPaths.add(parent);
+ } else {
+ String childSegment = p.lastSegment();
+ String knownChildSegment = childSegments.get(parent);
+ if (knownChildSegment == null) {
+ childSegments.put(parent, childSegment);
+ } else if (!childSegment.equals(knownChildSegment)) {
+ // The parent has more than 1 direct child folder -> we
+ // need to make a node for it.
+ folderPaths.add(parent);
+ }
+ }
+ }
+ }
+
+ IPath workingDirectory = new Path(repository.getWorkTree()
+ .getAbsolutePath());
+
+ List<StagingFolderEntry> folderEntries = new ArrayList<StagingFolderEntry>();
+ for (IPath folderPath : folderPaths) {
+ IPath parent = folderPath.removeLastSegments(1);
+ // Find first existing parent node, but stop at root
+ while (parent.segmentCount() != 0 && !folderPaths.contains(parent))
+ parent = parent.removeLastSegments(1);
+ if (parent.segmentCount() == 0) {
+ // Parent is root
+ StagingFolderEntry folderEntry = new StagingFolderEntry(
+ workingDirectory, folderPath, folderPath);
+ folderEntries.add(folderEntry);
+ } else {
+ // Parent is existing node
+ IPath nodePath = folderPath.makeRelativeTo(parent);
+ StagingFolderEntry folderEntry = new StagingFolderEntry(
+ workingDirectory, folderPath, nodePath);
+ folderEntries.add(folderEntry);
+ }
+ }
+
+ Collections.sort(folderEntries, FolderComparator.INSTANCE);
+ return folderEntries.toArray(new StagingFolderEntry[folderEntries
+ .size()]);
+ }
+
+ int getShownCount() {
+ String filterString = getFilterString();
+ if (filterString.length() == 0) {
+ return getCount();
+ } else {
+ int shownCount = 0;
+ for (StagingEntry entry : content) {
+ if (isInFilter(entry))
+ shownCount++;
+ }
+ return shownCount;
+ }
+ }
+
+ List<StagingEntry> getStagingEntriesFiltered(StagingFolderEntry folder) {
+ List<StagingEntry> stagingEntries = new ArrayList<StagingEntry>();
+ for (StagingEntry stagingEntry : content) {
+ if (folder.getLocation().isPrefixOf(stagingEntry.getLocation())) {
+ if (isInFilter(stagingEntry))
+ stagingEntries.add(stagingEntry);
+ }
+ }
+ return stagingEntries;
+ }
+
+ boolean isInFilter(StagingEntry stagingEntry) {
+ String filterString = getFilterString();
+ return filterString.length() == 0
+ || stagingEntry.getPath().toUpperCase()
+ .contains(filterString.toUpperCase());
+ }
+
+ private String getFilterString() {
+ return stagingView.getFilterString();
+ }
+
+ boolean hasVisibleChildren(StagingFolderEntry folder) {
+ if (getFilterString().length() == 0)
+ return true;
+ else
+ return !getStagingEntriesFiltered(folder).isEmpty();
}
- int getStagingEntryCount() {
- return content.length;
+ StagingEntry[] getStagingEntries() {
+ return content;
}
- public void inputChanged(Viewer viewer, Object oldInput,
- Object newInput) {
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (!(newInput instanceof StagingViewUpdate))
return;
@@ -66,9 +262,18 @@ public class StagingViewContentProvider implements
if (update.repository == null || update.indexDiff == null) {
content = new StagingEntry[0];
+ treeFolders = new StagingFolderEntry[0];
+ compactTreeFolders = new StagingFolderEntry[0];
return;
}
+ if (update.repository != repository) {
+ treeFolders = null;
+ compactTreeFolders = null;
+ }
+
+ repository = update.repository;
+
Set<StagingEntry> nodes = new TreeSet<StagingEntry>(
new Comparator<StagingEntry>() {
public int compare(StagingEntry o1, StagingEntry o2) {
@@ -86,8 +291,7 @@ public class StagingViewContentProvider implements
}
final IndexDiffData indexDiff = update.indexDiff;
- final Repository repository = update.repository;
- if (isWorkspace) {
+ if (unstagedSection) {
for (String file : indexDiff.getMissing())
if (indexDiff.getChanged().contains(file))
nodes.add(new StagingEntry(repository, MISSING_AND_CHANGED,
@@ -123,9 +327,31 @@ public class StagingViewContentProvider implements
}
content = nodes.toArray(new StagingEntry[nodes.size()]);
+
+ treeFolders = null;
+ compactTreeFolders = null;
}
public void dispose() {
// nothing to dispose
}
-}
+
+ /**
+ * @return StagingEntry count
+ */
+ public int getCount() {
+ if (content == null)
+ return 0;
+ else
+ return content.length;
+ }
+
+ private static class FolderComparator implements
+ Comparator<StagingFolderEntry> {
+ public static FolderComparator INSTANCE = new FolderComparator();
+ public int compare(StagingFolderEntry o1, StagingFolderEntry o2) {
+ return o1.getPath().toString().compareTo(o2.getPath().toString());
+ }
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java
index 92f944b..ede63ee 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingViewLabelProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2011, Bernard Leach <leachbj@bouncycastle.org>
+ * Copyright (C) 2011, 2013 Bernard Leach <leachbj@bouncycastle.org> and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -14,25 +14,27 @@ import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.decorators.DecorationResult;
import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator.DecorationHelper;
+import org.eclipse.egit.ui.internal.staging.StagingView.Presentation;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
-import org.eclipse.jface.viewers.BaseLabelProvider;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
-import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.IDecoration;
-import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
/**
* Label provider for {@link StagingEntry} objects
*/
-public class StagingViewLabelProvider extends BaseLabelProvider implements
- ITableLabelProvider, IStyledLabelProvider {
+public class StagingViewLabelProvider extends LabelProvider {
+ private StagingView stagingView;
+
+ private WorkbenchLabelProvider workbenchLabelProvider = new WorkbenchLabelProvider();
private Image DEFAULT = PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_OBJ_FILE);
@@ -49,6 +51,14 @@ public class StagingViewLabelProvider extends BaseLabelProvider implements
private boolean fileNameMode = false;
/**
+ * @param stagingView
+ */
+ public StagingViewLabelProvider(StagingView stagingView) {
+ super();
+ this.stagingView = stagingView;
+ }
+
+ /**
* Set file name mode to be enabled or disabled. This mode displays the
* names of the file first followed by the path to the folder that the file
* is in.
@@ -61,18 +71,6 @@ public class StagingViewLabelProvider extends BaseLabelProvider implements
return this;
}
- public Image getColumnImage(Object element, int columnIndex) {
- if (columnIndex == 0)
- return getImage(element);
- return null;
- }
-
- public String getColumnText(Object element, int columnIndex) {
- if (columnIndex == 0)
- return getStyledText(element).toString();
- return ""; //$NON-NLS-1$
- }
-
@Override
public void dispose() {
SUBMODULE.dispose();
@@ -100,45 +98,66 @@ public class StagingViewLabelProvider extends BaseLabelProvider implements
return (Image) this.resourceManager.get(decorated);
}
- public StyledString getStyledText(Object element) {
- final StagingEntry c = (StagingEntry) element;
- final DecorationResult decoration = new DecorationResult();
+ public Image getImage(Object element) {
+
+ if (element instanceof StagingFolderEntry) {
+ StagingFolderEntry c = (StagingFolderEntry) element;
+ if (c.getContainer() == null) {
+ return PlatformUI.getWorkbench().getSharedImages()
+ .getImage(ISharedImages.IMG_OBJ_FOLDER);
+ }
+ return workbenchLabelProvider
+ .getImage(((StagingFolderEntry) element).getContainer());
+ }
+
+ StagingEntry c = (StagingEntry) element;
+ DecorationResult decoration = new DecorationResult();
decorationHelper.decorate(decoration, c);
+ return getDecoratedImage(getEditorImage(c), decoration.getOverlay());
+ }
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof StagingFolderEntry) {
+ StagingFolderEntry stagingFolderEntry = (StagingFolderEntry) element;
+ return stagingFolderEntry.getNodePath().toString();
+ }
+
+ StagingEntry stagingEntry = (StagingEntry) element;
+ final DecorationResult decoration = new DecorationResult();
+ decorationHelper.decorate(decoration, stagingEntry);
final StyledString styled = new StyledString();
final String prefix = decoration.getPrefix();
final String suffix = decoration.getSuffix();
if (prefix != null)
styled.append(prefix, StyledString.DECORATIONS_STYLER);
- if (fileNameMode) {
- IPath parsed = Path.fromOSString(c.getPath());
- if (parsed.segmentCount() > 1) {
- styled.append(parsed.lastSegment());
- if (suffix != null)
- styled.append(suffix, StyledString.DECORATIONS_STYLER);
- styled.append(' ');
- styled.append('-', StyledString.QUALIFIER_STYLER);
- styled.append(' ');
- styled.append(parsed.removeLastSegments(1).toString(),
- StyledString.QUALIFIER_STYLER);
+ if (stagingView.getPresentation() == Presentation.LIST) {
+ if (fileNameMode) {
+ IPath parsed = Path.fromOSString(stagingEntry.getPath());
+ if (parsed.segmentCount() > 1) {
+ styled.append(parsed.lastSegment());
+ if (suffix != null)
+ styled.append(suffix, StyledString.DECORATIONS_STYLER);
+ styled.append(' ');
+ styled.append('-', StyledString.QUALIFIER_STYLER);
+ styled.append(' ');
+ styled.append(parsed.removeLastSegments(1).toString(),
+ StyledString.QUALIFIER_STYLER);
+ } else {
+ styled.append(stagingEntry.getPath());
+ if (suffix != null)
+ styled.append(suffix, StyledString.DECORATIONS_STYLER);
+ }
} else {
- styled.append(c.getPath());
+ styled.append(stagingEntry.getPath());
if (suffix != null)
styled.append(suffix, StyledString.DECORATIONS_STYLER);
}
} else {
- styled.append(c.getPath());
- if (suffix != null)
- styled.append(suffix, StyledString.DECORATIONS_STYLER);
+ styled.append(stagingEntry.getName());
}
-
- return styled;
+ return styled.toString();
}
- public Image getImage(Object element) {
- final StagingEntry c = (StagingEntry) element;
- final DecorationResult decoration = new DecorationResult();
- decorationHelper.decorate(decoration, c);
- return getDecoratedImage(getEditorImage(c), decoration.getOverlay());
- }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
index 4fd0849..06ec7ae 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties
@@ -1630,6 +1630,10 @@ StagingView_UnstageItemMenuLabel=Remove from Git Index
StagingView_StageItemMenuLabel=Add to Git Index
StagingView_IgnoreItemMenuLabel=Ignore
StagingView_DeleteItemMenuLabel=Delete
+StagingView_Presentation=Presentation
+StagingView_List=List
+StagingView_Tree=Tree
+StagingView_CompactTree=Compact Tree
StagingView_Find=Filter files
StagingViewContentProvider_SubmoduleError=Unhandled exception while analyzing submodules
StashApplyCommand_applyFailed=Applying stashed commit ''{0}'' failed due to ''{1}''