From 6bcaf8223ccf9838774138e1b9e9bb15b9d35703 Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Tue, 26 Jun 2012 00:55:49 +0200 Subject: [PATCH] [historyView] Highlight filtered files in file diff viewer The fix for bug 360073 changed the History view file diff viewer to show all files of a commit, regardless of the resource filter. This made it sometimes hard to find the files that the filter is focused on. This change improves that by rendering the files that are not matched by the filter in gray. The matching files are rendered in the same color as before. With this, the files can be found at a glance instead of reading through the paths. Bug: 393610 JGit-Dependency: Icf911fe6fca131b2567514f54d66636a44561af1 Change-Id: I03da4b38d1591495cb290909f0e4c6e52270e97f Signed-off-by: Matthias Sohn --- .../egit/ui/internal/commit/RepositoryCommit.java | 5 ++- .../ui/internal/history/CommitFileDiffViewer.java | 45 +++++++++++++++++++++- .../eclipse/egit/ui/internal/history/FileDiff.java | 41 ++++++++++++++++++-- .../internal/history/FileDiffContentProvider.java | 24 +++++++++++- .../ui/internal/history/FileDiffLabelProvider.java | 30 +++++++++++++-- .../egit/ui/internal/history/GitHistoryPage.java | 33 +++++++++++++++- 6 files changed, 165 insertions(+), 13 deletions(-) diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/RepositoryCommit.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/RepositoryCommit.java index 14cfc143e..a5befd111 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/RepositoryCommit.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/RepositoryCommit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 GitHub Inc. + * Copyright (c) 2011, 2012 GitHub Inc. 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 @@ -7,6 +7,7 @@ * * Contributors: * Kevin Sawicki (GitHub Inc.) - initial API and implementation + * Robin Stocker (independent) *******************************************************************************/ package org.eclipse.egit.ui.internal.commit; @@ -153,7 +154,7 @@ public class RepositoryCommit extends WorkbenchAdapter implements IAdaptable { try { for (RevCommit parent : commit.getParents()) revWalk.parseBody(parent); - diffs = FileDiff.compute(treewalk, commit); + diffs = FileDiff.compute(treewalk, commit, TreeFilter.ALL); } catch (IOException e) { diffs = new FileDiff[0]; } finally { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java index 3108c25f9..9b6703332 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java @@ -1,7 +1,7 @@ /******************************************************************************* * Copyright (C) 2008, 2012 Shawn O. Pearce * Copyright (C) 2012, Daniel Megert - * Copyright (C) 2012, Robin Stocker + * Copyright (C) 2012, 2013 Robin Stocker * Copyright (C) 2012, Gunnar Wagenknecht * * All rights reserved. This program and the accompanying materials @@ -16,6 +16,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.eclipse.compare.ITypedElement; import org.eclipse.core.resources.IFile; @@ -66,6 +67,8 @@ import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Table; @@ -79,6 +82,7 @@ import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.ShowInContext; +import org.eclipse.ui.themes.ColorUtil; /** * Viewer to display {@link FileDiff} objects in a table. @@ -139,7 +143,11 @@ public class CommitFileDiffViewer extends TableViewer { rawTable.setLinesVisible(true); - setLabelProvider(new FileDiffLabelProvider()); + Color fg = rawTable.getForeground(); + Color bg = rawTable.getBackground(); + RGB dimmedForegroundRgb = ColorUtil.blend(fg.getRGB(), bg.getRGB(), 60); + + setLabelProvider(new FileDiffLabelProvider(dimmedForegroundRgb)); setContentProvider(new FileDiffContentProvider()); addOpenListener(new IOpenListener() { public void open(final OpenEvent event) { @@ -374,6 +382,7 @@ public class CommitFileDiffViewer extends TableViewer { if (oldInput == null && input == null) return; super.inputChanged(input, oldInput); + revealFirstInterestingElement(); } /** @@ -621,4 +630,36 @@ public class CommitFileDiffViewer extends TableViewer { clipboard.setContents(new Object[] { r.toString() }, new Transfer[] { TextTransfer.getInstance() }, DND.CLIPBOARD); } + + /** + * @see FileDiffContentProvider#setInterestingPaths(Set) + * @param interestingPaths + */ + void setInterestingPaths(Set interestingPaths) { + ((FileDiffContentProvider) getContentProvider()).setInterestingPaths(interestingPaths); + } + + private void revealFirstInterestingElement() { + IStructuredContentProvider contentProvider = ((IStructuredContentProvider) getContentProvider()); + Object[] elements = contentProvider.getElements(getInput()); + if (elements.length <= 1) + return; + + for (final Object element : elements) { + if (element instanceof FileDiff) { + FileDiff fileDiff = (FileDiff) element; + boolean marked = fileDiff.isMarked(FileDiffContentProvider.INTERESTING_MARK_TREE_FILTER_INDEX); + if (marked) { + // Does not yet work reliably, see comment on bug 393610. + getTable().getDisplay().asyncExec(new Runnable() { + public void run() { + reveal(element); + } + }); + // Only reveal first + return; + } + } + } + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java index dd88cdfc2..ae258cd9c 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java @@ -2,6 +2,7 @@ * Copyright (C) 2007, Robin Rosenberg * Copyright (C) 2008, Shawn O. Pearce * Copyright (c) 2010, Stefan Lay + * Copyright (C) 2012, Robin Stocker * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -44,6 +45,8 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.treewalk.EmptyTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.TreeFilter; +import org.eclipse.jgit.treewalk.filter.TreeFilterMarker; import org.eclipse.ui.model.WorkbenchAdapter; /** @@ -69,13 +72,15 @@ public class FileDiff extends WorkbenchAdapter { * * @param walk * @param commit + * @param markTreeFilters optional filters for marking entries, see {@link #isMarked(int)} * @return non-null but possibly empty array of file diffs * @throws MissingObjectException * @throws IncorrectObjectTypeException * @throws CorruptObjectException * @throws IOException */ - public static FileDiff[] compute(final TreeWalk walk, final RevCommit commit) + public static FileDiff[] compute(final TreeWalk walk, + final RevCommit commit, final TreeFilter... markTreeFilters) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { final ArrayList r = new ArrayList(); @@ -89,7 +94,7 @@ public class FileDiff extends WorkbenchAdapter { } if (walk.getTreeCount() <= 2) { - List entries = DiffEntry.scan(walk); + List entries = DiffEntry.scan(walk, false, markTreeFilters); for (DiffEntry entry : entries) { final FileDiff d = new FileDiff(commit, entry); r.add(d); @@ -98,11 +103,18 @@ public class FileDiff extends WorkbenchAdapter { else { // DiffEntry does not support walks with more than two trees final int nTree = walk.getTreeCount(); final int myTree = nTree - 1; + + TreeFilterMarker treeFilterMarker = new TreeFilterMarker( + markTreeFilters); + while (walk.next()) { if (matchAnyParent(walk, myTree)) continue; - final FileDiffForMerges d = new FileDiffForMerges(commit); + int treeFilterMarks = treeFilterMarker.getMarks(walk); + + final FileDiffForMerges d = new FileDiffForMerges(commit, + treeFilterMarks); d.path = walk.getPathString(); int m0 = 0; for (int i = 0; i < myTree; i++) @@ -121,6 +133,8 @@ public class FileDiff extends WorkbenchAdapter { d.blobs[i] = walk.getObjectId(i); d.modes[i] = walk.getFileMode(i); } + + r.add(d); } @@ -294,6 +308,17 @@ public class FileDiff extends WorkbenchAdapter { } /** + * Whether the mark tree filter with the specified index matched during scan + * or not, see {@link #compute(TreeWalk, RevCommit, TreeFilter...)}. + * + * @param index the tree filter index to check + * @return true if it was marked, false otherwise + */ + public boolean isMarked(int index) { + return diffEntry != null && diffEntry.isMarked(index); + } + + /** * Create a file diff for a specified {@link RevCommit} and * {@link DiffEntry} * @@ -348,8 +373,11 @@ public class FileDiff extends WorkbenchAdapter { private FileMode[] modes; - private FileDiffForMerges(final RevCommit c) { + private final int treeFilterMarks; + + private FileDiffForMerges(final RevCommit c, int treeFilterMarks) { super (c, null); + this.treeFilterMarks = treeFilterMarks; } @Override @@ -371,5 +399,10 @@ public class FileDiff extends WorkbenchAdapter { public FileMode[] getModes() { return modes; } + + @Override + public boolean isMarked(int index) { + return (treeFilterMarks & (1L << index)) != 0; + } } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffContentProvider.java index 134cd16c0..efe7c8229 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffContentProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffContentProvider.java @@ -1,5 +1,6 @@ /******************************************************************************* * Copyright (C) 2008, Shawn O. Pearce + * Copyright (C) 2012, Robin Stocker * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -9,6 +10,7 @@ package org.eclipse.egit.ui.internal.history; import java.io.IOException; +import java.util.Set; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIText; @@ -16,18 +18,25 @@ import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.osgi.util.NLS; /** * Content provider for {@link FileDiff} objects */ public class FileDiffContentProvider implements IStructuredContentProvider { + + static final int INTERESTING_MARK_TREE_FILTER_INDEX = 0; + private TreeWalk walk; private RevCommit commit; private FileDiff[] diff; + private TreeFilter markTreeFilter = TreeFilter.ALL; + public void inputChanged(final Viewer newViewer, final Object oldInput, final Object newInput) { if (newInput != null) { @@ -40,10 +49,23 @@ public class FileDiffContentProvider implements IStructuredContentProvider { diff = null; } + /** + * Set the paths which are interesting and should be highlighted in the view. + * @param interestingPaths + */ + void setInterestingPaths(Set interestingPaths) { + if (interestingPaths != null) + this.markTreeFilter = PathFilterGroup.createFromStrings(interestingPaths); + else + this.markTreeFilter = TreeFilter.ALL; + // FileDiffs need to be updated + this.diff = null; + } + public Object[] getElements(final Object inputElement) { if (diff == null && walk != null && commit != null) try { - diff = FileDiff.compute(walk, commit); + diff = FileDiff.compute(walk, commit, markTreeFilter); } catch (IOException err) { Activator.handleError(NLS.bind(UIText.FileDiffContentProvider_errorGettingDifference, commit.getId()), err, false); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffLabelProvider.java index 099a8c6ae..bdb4ae04b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffLabelProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2008, Shawn O. Pearce + * Copyright (C) 2008, 2013 Shawn O. Pearce and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -12,17 +12,28 @@ 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.ITableColorProvider; import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; /** * Label provider for {@link FileDiff} objects */ public class FileDiffLabelProvider extends BaseLabelProvider implements - ITableLabelProvider { + ITableLabelProvider, ITableColorProvider { - private ResourceManager resourceManager = new LocalResourceManager( + private final ResourceManager resourceManager = new LocalResourceManager( JFaceResources.getResources()); + private final Color dimmedForegroundColor; + + /** + * @param dimmedForegroundRgb the color used for as foreground color for "unhighlighted" entries + */ + public FileDiffLabelProvider(RGB dimmedForegroundRgb) { + dimmedForegroundColor = resourceManager.createColor(dimmedForegroundRgb); + } public String getColumnText(final Object element, final int columnIndex) { if (columnIndex == 0) @@ -44,4 +55,17 @@ public class FileDiffLabelProvider extends BaseLabelProvider implements super.dispose(); } + public Color getForeground(Object element, int columnIndex) { + if (columnIndex == 0) { + final FileDiff c = (FileDiff) element; + if (!c.isMarked(FileDiffContentProvider.INTERESTING_MARK_TREE_FILTER_INDEX)) + return dimmedForegroundColor; + } + return null; + } + + public Color getBackground(Object element, int columnIndex) { + // Use default color + return null; + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java index 55315a243..d335d3e4b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java @@ -18,8 +18,10 @@ package org.eclipse.egit.ui.internal.history; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map.Entry; +import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; @@ -64,6 +66,7 @@ import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.events.ListenerHandle; @@ -77,6 +80,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revplot.PlotCommit; import org.eclipse.jgit.revplot.PlotWalk; import org.eclipse.jgit.revwalk.FollowFilter; +import org.eclipse.jgit.revwalk.RenameCallback; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.jgit.revwalk.RevObject; @@ -646,6 +650,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, private boolean currentFollowRenames; + /** Tracks the file names that are to be highlighted in the diff file viewer */ + private Set fileViewerInterestingPaths; + // react on changes to the relative date preference private final IPropertyChangeListener listener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { @@ -1469,6 +1476,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, graph.setInput(highlightFlag, list, asArray, input, true); if (toSelect != null) graph.selectCommit(toSelect); + if (getFollowRenames()) + updateInterestingPathsOfFileViewer(); if (trace) GitTraceLocation.getTrace().trace( GitTraceLocation.HISTORYVIEW.getLocation(), @@ -1488,6 +1497,10 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, GitTraceLocation.HISTORYVIEW.getLocation()); } + private void updateInterestingPathsOfFileViewer() { + fileViewer.setInterestingPaths(fileViewerInterestingPaths); + } + private void setWarningText(String warning) { if (warningComposite == null || warningComposite.isDisposed()) return; @@ -1739,6 +1752,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, private TreeWalk setupFileViewer(RevWalk walk, Repository db, List paths) { final TreeWalk fileWalker = createFileWalker(walk, db, paths); fileViewer.setTreeWalk(db, fileWalker); + fileViewer.setInterestingPaths(fileViewerInterestingPaths); fileViewer.refresh(); fileViewer.addSelectionChangedListener(commentViewer); return fileWalker; @@ -1757,6 +1771,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, for (FilterPath filterPath : paths) selectedPaths.add(filterPath.getPath()); + fileViewerInterestingPaths = new HashSet(selectedPaths); TreeFilter followFilter = createFollowFilterFor(selectedPaths); walk.setTreeFilter(followFilter); } else if (paths.size() > 0) { @@ -1767,9 +1782,11 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, walk.setTreeFilter(AndTreeFilter.create(PathFilterGroup .createFromStrings(stringPaths), TreeFilter.ANY_DIFF)); + fileViewerInterestingPaths = new HashSet(stringPaths); } else { pathFilters = null; walk.setTreeFilter(TreeFilter.ALL); + fileViewerInterestingPaths = null; } return fileWalker; } @@ -1786,7 +1803,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, List followFilters = new ArrayList(paths.size()); for (String path : paths) - followFilters.add(FollowFilter.create(path)); + followFilters.add(createFollowFilter(path)); if (followFilters.size() == 1) return followFilters.get(0); @@ -1794,6 +1811,20 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, return OrTreeFilter.create(followFilters); } + private FollowFilter createFollowFilter(String path) { + FollowFilter followFilter = FollowFilter.create(path); + followFilter.setRenameCallback(new RenameCallback() { + @Override + public void renamed(DiffEntry entry) { + if (fileViewerInterestingPaths != null) { + fileViewerInterestingPaths.add(entry.getOldPath()); + fileViewerInterestingPaths.add(entry.getNewPath()); + } + } + }); + return followFilter; + } + /** * @return Returns true if all filterpaths refer to plain files, * or if the list is empty. -- 2.11.4.GIT