Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf2019-12-03 21:17:35 +0000
committerMichael Keppler2019-12-13 17:30:05 +0000
commitb2e98cd3ae4bc45153e5424c331f3cdaa936f537 (patch)
treecaf5e39d82d3595e1024d1cac0c6241884852da5
parentac9e00bebef50c2b7682cd349e7e92ff3ef0efd3 (diff)
downloadegit-b2e98cd3ae4bc45153e5424c331f3cdaa936f537.tar.gz
egit-b2e98cd3ae4bc45153e5424c331f3cdaa936f537.tar.xz
egit-b2e98cd3ae4bc45153e5424c331f3cdaa936f537.zip
[repo view] Simpler refresh, better decorator setup, simpler listeners
Instead of a scheduling a job that schedules a UI refresh simply schedule the UI refresh directly. Reduce the default delay a little. Also, there is no need to use a new input. Refreshing the viewer will pick up structural changes. The lightweight decorator was setup in a somewhat non-standard way not really supported by the CNF. Use a simple non-decorating label provider in the view, and let the framework do all the decorating. This has multiple advantages: there's no flickering on refreshes. Icon decorations can finally be done in the lightweight decorator. This also brings back the gitflow icon overlay. And there's no longer a need for caching "last used" labels to avoid flickering in text decorations. However, out of the box the framework does not support having label text after the decoration. Add special-case handling for updating a ViewerCell and add the directories of repositories and working trees only then. If this were done in getStyledText() of the label provider, the directories would appear before the decoration. Note that both the simpler refresh and the lightweight decorator setup belong together. Doing only one or the other leads to flickering on refresh. Use lambdas for listeners. Bug: 553841 Change-Id: I735da30934c650680d60781ae58f7f354089d7d0 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewTestUtils.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectRepositoryPage.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushTagsPage.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java192
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeDecorator.java136
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeLabelProvider.java142
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeWorkbenchAdapter.java89
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/DeleteRepositoryGroupConfirmDialog.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchPage.java2
11 files changed, 217 insertions, 359 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewTestUtils.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewTestUtils.java
index 5190cf918..9e95b5207 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewTestUtils.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/view/repositories/GitRepositoriesViewTestUtils.java
@@ -44,7 +44,7 @@ public class GitRepositoriesViewTestUtils {
@Override
public void run() {
- providerRef.set(new RepositoryTreeNodeLabelProvider());
+ providerRef.set(new RepositoryTreeNodeLabelProvider(true));
}
});
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectRepositoryPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectRepositoryPage.java
index 1f57fb4d8..2a4ce48bd 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectRepositoryPage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectRepositoryPage.java
@@ -179,7 +179,7 @@ public class GitSelectRepositoryPage extends WizardPage {
return false;
}
});
- tv.setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ tv.setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
tv.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java
index fce34ef52..4b998c117 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java
@@ -200,7 +200,7 @@ public class GitSelectWizardPage extends WizardPage {
tv.setContentProvider(cp);
GridDataFactory.fillDefaults().grab(true, true).hint(SWT.DEFAULT, 200)
.applyTo(tv.getTree());
- tv.setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ tv.setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
tv.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java
index 28c89de99..e70688062 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/AbstractBranchSelectionDialog.java
@@ -32,8 +32,8 @@ import org.eclipse.egit.ui.internal.repository.tree.BranchHierarchyNode;
import org.eclipse.egit.ui.internal.repository.tree.LocalNode;
import org.eclipse.egit.ui.internal.repository.tree.RefNode;
import org.eclipse.egit.ui.internal.repository.tree.RemoteTrackingNode;
-import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeSorter;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
+import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeSorter;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
import org.eclipse.egit.ui.internal.repository.tree.TagNode;
import org.eclipse.egit.ui.internal.repository.tree.TagsNode;
@@ -297,7 +297,7 @@ public abstract class AbstractBranchSelectionDialog extends TitleAreaDialog {
selectionModel | SWT.BORDER, filter, true);
branchTree = tree.getViewer();
branchTree.setUseHashlookup(true);
- branchTree.setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ branchTree.setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
branchTree.setContentProvider(new RepositoriesViewContentProvider());
ColumnViewerToolTipSupport.enableFor(branchTree);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushTagsPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushTagsPage.java
index 7269f001d..4943dbadf 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushTagsPage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushTagsPage.java
@@ -130,7 +130,7 @@ public class PushTagsPage extends WizardPage {
TagsNode tagsNode = new TagsNode(null, repository);
ContentProvider contentProvider = new ContentProvider(tagsNode);
treeViewer.setContentProvider(contentProvider);
- treeViewer.setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ treeViewer.setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
treeViewer.setComparator(new ViewerComparator(
CommonUtils.STRING_ASCENDING_COMPARATOR));
treeViewer.setInput(tagsNode);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java
index a9aed1886..a208ae43a 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java
@@ -35,16 +35,13 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.commands.IStateListener;
import org.eclipse.core.commands.State;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.egit.core.AdapterUtils;
import org.eclipse.egit.core.RepositoryCache;
import org.eclipse.egit.core.RepositoryUtil;
@@ -97,12 +94,11 @@ import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
-import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.FocusCellHighlighter;
-import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
@@ -114,13 +110,11 @@ import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewerEditor;
import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
+import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.Window;
-import org.eclipse.jgit.events.ConfigChangedEvent;
import org.eclipse.jgit.events.ConfigChangedListener;
-import org.eclipse.jgit.events.IndexChangedEvent;
import org.eclipse.jgit.events.IndexChangedListener;
import org.eclipse.jgit.events.ListenerHandle;
-import org.eclipse.jgit.events.RefsChangedEvent;
import org.eclipse.jgit.events.RefsChangedListener;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.osgi.util.NLS;
@@ -174,7 +168,7 @@ import org.eclipse.ui.views.properties.PropertySheet;
import org.eclipse.ui.views.properties.PropertySheetPage;
/**
- * The "Git Repositories View"
+ * The "Git Repositories View".
*/
public class RepositoriesView extends CommonNavigator implements IShowInSource, IShowInTargetList {
@@ -200,20 +194,22 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
private static final String SINGLE_REPO_CONTEXT_ID = VIEW_ID
+ ".SingleRepository"; //$NON-NLS-1$
- private static final long DEFAULT_REFRESH_DELAY = 1000;
+ /**
+ * Delay between refreshes in milliseconds. Used to avoid overwhelming the
+ * viewer with refreshes when many change events arrive from repositories.
+ */
+ private static final long DEFAULT_REFRESH_DELAY = 300L;
private final Set<Repository> repositories = new HashSet<>();
- private final RefsChangedListener myRefsChangedListener;
+ private final RefsChangedListener myRefsChangedListener = event -> scheduleRefresh();
- private final IndexChangedListener myIndexChangedListener;
+ private final IndexChangedListener myIndexChangedListener = event -> scheduleRefresh();
- private final ConfigChangedListener myConfigChangeListener;
+ private final ConfigChangedListener myConfigChangeListener = event -> scheduleRefresh();
private final List<ListenerHandle> myListeners = new LinkedList<>();
- private Job scheduledJob;
-
private RefreshUiJob refreshUiJob;
private final RepositoryUtil repositoryUtil;
@@ -224,10 +220,6 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
private StackLayout layout;
- private volatile long lastInputChange = 0L;
-
- private volatile long lastInputUpdate = -1L;
-
private State reactOnSelection;
private IWorkbenchPart lastSelectionPart;
@@ -285,7 +277,11 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
private final IStateListener stateChangeListener = (state,
oldValue) -> refresh();
- private final IPreferenceChangeListener configurationListener;
+ private final IPreferenceChangeListener configurationListener = event -> {
+ if (RepositoryUtil.PREFS_DIRECTORIES_REL.equals(event.getKey())) {
+ refresh();
+ }
+ };
private IContextActivation renameContext;
@@ -301,39 +297,6 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
repositoryUtil = Activator.getDefault().getRepositoryUtil();
repositoryCache = org.eclipse.egit.core.Activator.getDefault()
.getRepositoryCache();
-
- configurationListener = new IPreferenceChangeListener() {
- @Override
- public void preferenceChange(PreferenceChangeEvent event) {
- if (RepositoryUtil.PREFS_DIRECTORIES_REL
- .equals(event.getKey())) {
- lastInputChange = System.currentTimeMillis();
- scheduleRefresh(DEFAULT_REFRESH_DELAY, null);
- }
- }
- };
-
- myRefsChangedListener = new RefsChangedListener() {
- @Override
- public void onRefsChanged(RefsChangedEvent e) {
- scheduleRefresh(DEFAULT_REFRESH_DELAY, null);
- }
- };
-
- myIndexChangedListener = new IndexChangedListener() {
- @Override
- public void onIndexChanged(IndexChangedEvent event) {
- scheduleRefresh(DEFAULT_REFRESH_DELAY, null);
-
- }
- };
-
- myConfigChangeListener = new ConfigChangedListener() {
- @Override
- public void onConfigChanged(ConfigChangedEvent event) {
- scheduleRefresh(DEFAULT_REFRESH_DELAY, null);
- }
- };
}
/**
@@ -773,7 +736,7 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
private void initRepositoriesAndListeners() {
synchronized (repositories) {
repositories.clear();
- unregisterRepositoryListener();
+ unregisterRepositoryListeners();
Set<File> dirs = new HashSet<>();
// listen for repository changes
for (String dir : repositoryUtil.getConfiguredRepositories()) {
@@ -823,11 +786,6 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
if (branchHierarchy != null) {
branchHierarchy.removeListener(stateChangeListener);
}
- // make sure to cancel the refresh job
- if (this.scheduledJob != null) {
- this.scheduledJob.cancel();
- this.scheduledJob = null;
- }
refreshUiJob.cancel();
repositoryUtil.getPreferences().removePreferenceChangeListener(
@@ -836,8 +794,7 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
ISelectionService srv = CommonUtils.getService(getSite(), ISelectionService.class);
srv.removePostSelectionListener(selectionChangedListener);
- // remove RepositoryChangedListener
- unregisterRepositoryListener();
+ unregisterRepositoryListeners();
repositories.clear();
super.dispose();
@@ -945,7 +902,7 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
* Refresh Repositories View
*/
public void refresh() {
- lastInputUpdate = -1L;
+ initRepositoriesAndListeners();
scheduleRefresh(0, null);
}
@@ -954,61 +911,16 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
GitTraceLocation.REPOSITORIESVIEW.getLocation(), message);
}
- private synchronized void scheduleRefresh(long delay, Runnable uiTask) {
- if (GitTraceLocation.REPOSITORIESVIEW.isActive()) {
- trace("Entering scheduleRefresh()"); //$NON-NLS-1$
- }
+ private void scheduleRefresh() {
+ scheduleRefresh(DEFAULT_REFRESH_DELAY, null);
+ }
- refreshUiJob.cancel();
+ private synchronized void scheduleRefresh(long delay, Runnable uiTask) {
refreshUiJob.uiTask.compareAndSet(null, uiTask);
-
- if (scheduledJob != null) {
- schedule(scheduledJob, delay);
- return;
- }
-
- Job job = new Job("Refreshing Git Repositories data") { //$NON-NLS-1$
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- final CommonViewer tv = getCommonViewer();
- if (!UIUtils.isUsable(tv)) {
- return Status.CANCEL_STATUS;
- }
- final boolean trace = GitTraceLocation.REPOSITORIESVIEW
- .isActive();
- final boolean needsNewInput = lastInputChange > lastInputUpdate;
- if (trace) {
- trace("Running the update, new input required: " //$NON-NLS-1$
- + (lastInputChange > lastInputUpdate));
- }
- lastInputUpdate = System.currentTimeMillis();
- if (needsNewInput) {
- initRepositoriesAndListeners();
- }
-
- refreshUiJob.needsNewInput = needsNewInput;
- refreshUiJob.schedule();
- if (monitor.isCanceled()) {
- return Status.CANCEL_STATUS;
- }
- return Status.OK_STATUS;
- }
-
- @Override
- public boolean belongsTo(Object family) {
- return JobFamilies.REPO_VIEW_REFRESH.equals(family);
- }
-
- };
- job.setSystem(true);
- job.setUser(false);
- schedule(job, delay);
- scheduledJob = job;
+ refreshUiJob.schedule(delay);
}
class RefreshUiJob extends WorkbenchJob {
- volatile boolean needsNewInput;
final AtomicReference<Runnable> uiTask = new AtomicReference<>();
RefreshUiJob() {
@@ -1036,16 +948,8 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
return Status.CANCEL_STATUS;
}
- if (needsNewInput) {
- // keep expansion state and selection so that we can
- // restore the tree after update
- Object[] expanded = tv.getExpandedElements();
- tv.setInput(ResourcesPlugin.getWorkspace().getRoot());
- tv.setExpandedElements(expanded);
- afterRefresh(tv);
- } else {
- tv.refresh(true);
- }
+ tv.refresh(true);
+
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
@@ -1079,20 +983,8 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
}
}
- private void schedule(Job job, long delay) {
- IWorkbenchSiteProgressService service = CommonUtils.getService(getSite(), IWorkbenchSiteProgressService.class);
-
- if (GitTraceLocation.REPOSITORIESVIEW.isActive()) {
- GitTraceLocation.getTrace().trace(
- GitTraceLocation.REPOSITORIESVIEW.getLocation(),
- "Scheduling refresh job"); //$NON-NLS-1$
- }
- service.schedule(job, delay);
- }
-
- private void unregisterRepositoryListener() {
- for (ListenerHandle lh : myListeners)
- lh.remove();
+ private void unregisterRepositoryListeners() {
+ myListeners.forEach(ListenerHandle::remove);
myListeners.clear();
}
@@ -1394,9 +1286,9 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
}
/**
- * Customized {@link CommonViewer} that doesn't create a decorating label
- * provider -- our label provider already does so, and we don't want double
- * decorations.
+ * Customized {@link CommonViewer} that switches back to the empty area if
+ * the tree view becomes empty, and that adds additional information at the
+ * end of labels.
*/
private class RepositoriesCommonViewer extends CommonViewer {
@@ -1408,12 +1300,8 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
@Override
protected void init() {
super.init();
- IBaseLabelProvider labelProvider = getLabelProvider();
- // Our label provider already decorates. Avoid double decorating.
- if (labelProvider instanceof DecoratingStyledCellLabelProvider) {
- ((DecoratingStyledCellLabelProvider) labelProvider)
- .setLabelDecorator(null);
- }
+ setLabelProvider(new PathAddingLabelProvider(
+ getNavigatorContentService().createCommonLabelProvider()));
}
@Override
@@ -1428,4 +1316,18 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
afterRefresh(this);
}
}
+
+ @SuppressWarnings("restriction")
+ private static class PathAddingLabelProvider extends
+ org.eclipse.ui.internal.navigator.NavigatorDecoratingLabelProvider {
+
+ public PathAddingLabelProvider(ILabelProvider commonLabelProvider) {
+ super(commonLabelProvider);
+ }
+
+ @Override
+ public void update(ViewerCell cell) {
+ RepositoryTreeNodeLabelProvider.update(cell, super::update);
+ }
+ }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeDecorator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeDecorator.java
index b2cea3691..f046dedc5 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeDecorator.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeDecorator.java
@@ -28,6 +28,7 @@ import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.CommonUtils;
+import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.decorators.DecoratorRepositoryStateCache;
import org.eclipse.egit.ui.internal.decorators.GitDecorator;
@@ -42,6 +43,7 @@ import org.eclipse.egit.ui.internal.repository.tree.TagNode;
import org.eclipse.egit.ui.internal.repository.tree.command.ToggleBranchCommitCommand;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -124,44 +126,118 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
Repository repository = node.getRepository();
if (repository != null) {
UnitOfWork.execute(repository,
- () -> decorateText(node, repository, decoration));
+ () -> decorateNode(node, repository, decoration));
} else if (node.getType() == RepositoryTreeNodeType.REPOGROUP) {
decorateRepositoryGroup(node, decoration);
}
}
+ private void decorateNode(RepositoryTreeNode<?> node,
+ @NonNull Repository repository, IDecoration decoration) {
+ decorateText(node, repository, decoration);
+ decorateIcon(node, repository, decoration);
+ }
+
+ private void decorateIcon(RepositoryTreeNode<?> node,
+ @NonNull Repository repository, IDecoration decoration) {
+ switch (node.getType()) {
+ case TAG:
+ case ADDITIONALREF:
+ case REF:
+ // if the branch or tag is checked out,
+ // we want to decorate the corresponding
+ // node with a little check indicator
+ String refName = ((Ref) node.getObject()).getName();
+ Ref leaf = ((Ref) node.getObject()).getLeaf();
+
+ String compareString = null;
+ String branchName = DecoratorRepositoryStateCache.INSTANCE
+ .getFullBranchName(repository);
+ if (branchName == null) {
+ return;
+ }
+ if (refName.startsWith(Constants.R_HEADS)) {
+ // local branch: HEAD would be on the branch
+ compareString = refName;
+ } else if (refName.startsWith(Constants.R_TAGS)) {
+ // tag: HEAD would be on the commit id to which the tag is
+ // pointing
+ TagNode tagNode = (TagNode) node;
+ compareString = tagNode.getCommitId();
+ } else if (refName.startsWith(Constants.R_REMOTES)) {
+ // remote branch: branch name is object id in detached HEAD
+ // state
+ ObjectId objectId = leaf.getObjectId();
+ if (objectId != null) {
+ String leafName = objectId.getName();
+ if (leafName.equals(branchName)) {
+ decoration.addOverlay(UIIcons.OVR_CHECKEDOUT,
+ IDecoration.TOP_LEFT);
+ return;
+ }
+ }
+ } else if (refName.equals(Constants.HEAD)) {
+ decoration.addOverlay(UIIcons.OVR_CHECKEDOUT,
+ IDecoration.TOP_LEFT);
+ return;
+ } else {
+ String leafname = leaf.getName();
+ if (leafname.startsWith(Constants.R_REFS)
+ && leafname.equals(branchName)) {
+ decoration.addOverlay(UIIcons.OVR_CHECKEDOUT,
+ IDecoration.TOP_LEFT);
+ return;
+ }
+ ObjectId objectId = leaf.getObjectId();
+ if (objectId != null && objectId
+ .equals(DecoratorRepositoryStateCache.INSTANCE
+ .getHead(repository))) {
+ decoration.addOverlay(UIIcons.OVR_CHECKEDOUT,
+ IDecoration.TOP_LEFT);
+ }
+ // some other symbolic reference
+ return;
+ }
+
+ if (compareString != null && compareString.equals(branchName)) {
+ decoration.addOverlay(UIIcons.OVR_CHECKEDOUT,
+ IDecoration.TOP_LEFT);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
private void decorateText(RepositoryTreeNode<?> node,
@NonNull Repository repository, IDecoration decoration) {
- boolean decorated = false;
switch (node.getType()) {
case REPO:
- decorated = decorateRepository(node, repository, decoration);
+ decorateRepository(node, repository, decoration);
break;
case ADDITIONALREF:
- decorated = decorateAdditionalRef((AdditionalRefNode) node,
+ decorateAdditionalRef((AdditionalRefNode) node,
decoration);
break;
case REF:
- decorated = decorateRef((RefNode) node, decoration);
+ decorateRef((RefNode) node, decoration);
break;
case TAG:
- decorated = decorateTag((TagNode) node, decoration);
+ decorateTag((TagNode) node, decoration);
break;
case STASHED_COMMIT:
- decorated = decorateStash((StashedCommitNode) node, decoration);
+ decorateStash((StashedCommitNode) node, decoration);
break;
case SUBMODULES:
- decorated = decorateSubmodules(repository, decoration);
+ decorateSubmodules(repository, decoration);
break;
default:
return;
}
- if (!decorated) {
- ensureCorrectLabelCaching(decoration);
- }
}
- private boolean decorateAdditionalRef(AdditionalRefNode node,
+ private void decorateAdditionalRef(AdditionalRefNode node,
IDecoration decoration) {
Ref ref = node.getObject();
StringBuilder suffix = new StringBuilder();
@@ -182,22 +258,19 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
UIText.RepositoriesViewLabelProvider_UnbornBranchText);
}
decoration.addSuffix(suffix.toString());
- return true;
}
- private boolean decorateRef(RefNode node, IDecoration decoration) {
+ private void decorateRef(RefNode node, IDecoration decoration) {
if (verboseBranchMode) {
RevCommit latest = getLatestCommit(node);
if (latest != null) {
decoration.addSuffix(" " + abbreviate(latest) + ' ' //$NON-NLS-1$
+ latest.getShortMessage());
- return true;
}
}
- return false;
}
- private boolean decorateRepository(RepositoryTreeNode<?> node,
+ private void decorateRepository(RepositoryTreeNode<?> node,
@NonNull Repository repository, IDecoration decoration) {
boolean isSubModule = node.getParent() != null && node.getParent()
.getType() == RepositoryTreeNodeType.SUBMODULES;
@@ -209,7 +282,7 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
Ref head = DecoratorRepositoryStateCache.INSTANCE
.getHeadRef(repository);
if (head == null) {
- return false;
+ return;
}
suffix.append(OPEN_BRACKET);
if (head.isSymbolic()) {
@@ -231,7 +304,7 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
String branch = DecoratorRepositoryStateCache.INSTANCE
.getCurrentBranchLabel(repository);
if (branch == null) {
- return false;
+ return;
}
suffix.append(OPEN_BRACKET);
suffix.append(branch);
@@ -250,7 +323,6 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
suffix.append(']');
}
decoration.addSuffix(suffix.toString());
- return true;
}
private void decorateRepositoryGroup(RepositoryTreeNode<?> node,
@@ -289,58 +361,40 @@ public class RepositoryTreeNodeDecorator extends GitDecorator
}
}
}
- boolean decorated = false;
if (markGroupDirty) {
- decorated = true;
decoration.addPrefix(HAS_CHANGES_PREFIX);
}
if (numberOfBranches == 1) {
- decorated = true;
String repoLabel = singleRepoName != null ? singleRepoName
: MULTIPLE_REPOSITORIES;
decoration.addSuffix(
OPEN_BRACKET + repoLabel + ' ' + singleBranch + ']');
} else if (numberOfDirectories > 1) {
- decorated = true;
decoration.addSuffix(OPEN_PARENTHESIS + numberOfDirectories + ')');
}
- if (!decorated) {
- ensureCorrectLabelCaching(decoration);
- }
- }
-
- private void ensureCorrectLabelCaching(IDecoration decoration) {
- // Ensure the caching of last labels in
- // RepositoryTreeNodeLabelProvider works
- decoration.addSuffix(" ");//$NON-NLS-1$
}
- private boolean decorateStash(StashedCommitNode node,
+ private void decorateStash(StashedCommitNode node,
IDecoration decoration) {
RevCommit commit = node.getObject();
decoration.addSuffix(
OPEN_BRACKET + abbreviate(commit) + "] " //$NON-NLS-1$
+ commit.getShortMessage());
- return true;
}
- private boolean decorateSubmodules(@NonNull Repository repository,
+ private void decorateSubmodules(@NonNull Repository repository,
IDecoration decoration) {
if (haveSubmoduleChanges(repository)) {
decoration.addPrefix(HAS_CHANGES_PREFIX);
- return true;
}
- return false;
}
- private boolean decorateTag(TagNode node, IDecoration decoration) {
+ private void decorateTag(TagNode node, IDecoration decoration) {
if (verboseBranchMode && node.getCommitId() != null
&& node.getCommitId().length() > 0) {
decoration.addSuffix(" " + node.getCommitId().substring(0, 7) + ' ' //$NON-NLS-1$
+ node.getCommitShortMessage());
- return true;
}
- return false;
}
private RevCommit getLatestCommit(RepositoryTreeNode node) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeLabelProvider.java
index 392150561..458769d15 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeLabelProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeLabelProvider.java
@@ -15,7 +15,8 @@
*******************************************************************************/
package org.eclipse.egit.ui.internal.repository;
-import java.util.WeakHashMap;
+import java.util.Arrays;
+import java.util.function.Consumer;
import org.eclipse.egit.ui.internal.GitLabels;
import org.eclipse.egit.ui.internal.groups.RepositoryGroup;
@@ -28,10 +29,13 @@ import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
import org.eclipse.egit.ui.internal.repository.tree.WorkingDirNode;
import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
+import org.eclipse.jface.viewers.IDecorationContext;
+import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.custom.StyleRange;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchLabelProvider;
@@ -50,91 +54,36 @@ public class RepositoryTreeNodeLabelProvider
private final boolean showPaths;
/**
- * Keeps the last label. If the label we originally get is undecorated, we
- * return this last decorated label instead to prevent flickering. When the
- * asynchronous lightweight decorator then has computed the decoration, the
- * label will be updated. Note that this works only because our
- * RepositoryTreeNodeDecorator always decorates! (If there's no decoration,
- * it appends a single blank to ensure the decorated label is different from
- * the undecorated one.)
- * <p>
- * For images, there is no such work-around, and thus we need to do the
- * image decorations in the label provider (in the
- * RepositoryTreeNodeWorkbenchAdapter in our case) in the UI thread.
- */
- private final WeakHashMap<Object, StyledString> previousDecoratedLabels = new WeakHashMap<>();
-
- /**
- * Creates a new {@link RepositoryTreeNodeLabelProvider} that shows the
- * paths for repositories and working tree nodes.
+ * Creates a new {@link RepositoryTreeNodeLabelProvider} that neither
+ * decorates nor shows paths.
*/
public RepositoryTreeNodeLabelProvider() {
- this(true);
+ this(new WorkbenchLabelProvider(), null, null, false);
}
/**
- * Creates a new {@link RepositoryTreeNodeLabelProvider}.
+ * Creates a new {@link RepositoryTreeNodeLabelProvider} that decorates and
+ * optionally shows paths.
*
* @param showPaths
- * whether to show the file system paths for repositories and
- * working tree nodes
+ * whether to show paths
*/
public RepositoryTreeNodeLabelProvider(boolean showPaths) {
- this(new WorkbenchLabelProvider(), showPaths);
+ this(new WorkbenchLabelProvider(), PlatformUI.getWorkbench()
+ .getDecoratorManager().getLabelDecorator(), null, showPaths);
}
private RepositoryTreeNodeLabelProvider(
- WorkbenchLabelProvider labelProvider, boolean showPaths) {
- super(labelProvider, PlatformUI.getWorkbench()
- .getDecoratorManager().getLabelDecorator(), null);
+ WorkbenchLabelProvider labelProvider, ILabelDecorator decorator,
+ IDecorationContext decorationContext, boolean showPaths) {
+ super(labelProvider, decorator, decorationContext);
this.labelProvider = labelProvider;
this.showPaths = showPaths;
}
@Override
- public void dispose() {
- super.dispose();
- previousDecoratedLabels.clear();
- }
-
- @Override
public StyledString getStyledText(Object element) {
- StyledString decoratedLabel = super.getStyledText(element);
- String decoratedValue = decoratedLabel.getString();
- String simpleValue = labelProvider.getText(element);
- if (decoratedValue.equals(simpleValue)) {
- // Decoration not available yet... but may be shortly. Try to
- // prevent flickering by returning the previous decorated label, if
- // any.
- StyledString previousLabel = previousDecoratedLabels.get(element);
- if (previousLabel != null) {
- return previousLabel;
- }
- } else if (decoratedValue.trim().equals(simpleValue)) {
- // No decoration...
- decoratedLabel = labelProvider.getStyledText(element);
- }
- if (showPaths) {
- if (element instanceof RepositoryNode) {
- Repository repository = ((RepositoryNode) element)
- .getRepository();
- if (repository != null) {
- decoratedLabel.append(" - ", StyledString.QUALIFIER_STYLER) //$NON-NLS-1$
- .append(repository.getDirectory().getAbsolutePath(),
- StyledString.QUALIFIER_STYLER);
- }
- } else if (element instanceof WorkingDirNode) {
- Repository repository = ((WorkingDirNode) element)
- .getRepository();
- if (repository != null) {
- decoratedLabel.append(" - ", StyledString.QUALIFIER_STYLER) //$NON-NLS-1$
- .append(repository.getWorkTree().getAbsolutePath(),
- StyledString.QUALIFIER_STYLER);
- }
- }
- }
- previousDecoratedLabels.put(element, decoratedLabel);
- return decoratedLabel;
+ return super.getStyledText(element);
}
@Override
@@ -143,13 +92,6 @@ public class RepositoryTreeNodeLabelProvider
}
@Override
- public Image getImage(Object element) {
- // We know that the decorator for RepositoryTreeNodes will not decorate
- // the image; our label provider will do so already.
- return labelProvider.getImage(element);
- }
-
- @Override
public String getToolTipText(Object element) {
if (element instanceof AdditionalRefNode) {
AdditionalRefNode additionalRefNode = (AdditionalRefNode) element;
@@ -160,6 +102,15 @@ public class RepositoryTreeNodeLabelProvider
}
@Override
+ public void update(ViewerCell cell) {
+ if (showPaths) {
+ update(cell, super::update);
+ } else {
+ super.update(cell);
+ }
+ }
+
+ @Override
public void restoreState(IMemento memento) {
// empty
}
@@ -198,4 +149,43 @@ public class RepositoryTreeNodeLabelProvider
public void init(ICommonContentExtensionSite config) {
// empty
}
+
+ static void update(ViewerCell cell, Consumer<ViewerCell> updater) {
+ Object element = cell.getElement();
+ if (element instanceof RepositoryNode
+ || element instanceof WorkingDirNode) {
+ String textBefore = cell.getText();
+ StyleRange[] rangesBefore = cell.getStyleRanges();
+ updater.accept(cell);
+ String textAfter = cell.getText();
+ StyleRange[] rangesAfter = cell.getStyleRanges();
+ if (textBefore.equals(textAfter)
+ && Arrays.equals(rangesBefore, rangesAfter)) {
+ // Decorating delegate decided to wait.
+ return;
+ }
+ Repository repository = ((RepositoryTreeNode<?>) element)
+ .getRepository();
+ if (repository == null) {
+ return;
+ }
+ String newText = " - "; //$NON-NLS-1$
+ if (element instanceof RepositoryNode) {
+ newText += repository.getDirectory().getAbsolutePath();
+ } else if (element instanceof WorkingDirNode) {
+ newText += repository.getWorkTree().getAbsolutePath();
+ }
+ StyleRange style = new StyleRange();
+ style.start = textAfter.length();
+ style.length = newText.length();
+ StyledString.QUALIFIER_STYLER.applyStyles(style);
+ StyleRange[] newRanges = new StyleRange[rangesAfter.length + 1];
+ System.arraycopy(rangesAfter, 0, newRanges, 0, rangesAfter.length);
+ newRanges[newRanges.length - 1] = style;
+ cell.setText(textAfter + newText);
+ cell.setStyleRanges(newRanges);
+ } else {
+ updater.accept(cell);
+ }
+ }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeWorkbenchAdapter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeWorkbenchAdapter.java
index f80c3800c..4d6f09450 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeWorkbenchAdapter.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoryTreeNodeWorkbenchAdapter.java
@@ -14,22 +14,17 @@ import java.io.File;
import java.text.MessageFormat;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.egit.ui.internal.DecorationOverlayDescriptor;
import org.eclipse.egit.ui.internal.GitLabels;
import org.eclipse.egit.ui.internal.ResourcePropertyTester;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
-import org.eclipse.egit.ui.internal.decorators.DecoratorRepositoryStateCache;
import org.eclipse.egit.ui.internal.groups.RepositoryGroup;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
import org.eclipse.egit.ui.internal.repository.tree.StashedCommitNode;
import org.eclipse.egit.ui.internal.repository.tree.TagNode;
import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.viewers.IDecoration;
-import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.ui.PlatformUI;
@@ -63,18 +58,6 @@ public class RepositoryTreeNodeWorkbenchAdapter extends WorkbenchAdapter {
return null;
}
RepositoryTreeNode<?> node = (RepositoryTreeNode) object;
- ImageDescriptor base = getBaseImageDescriptor(node);
- if (base == null) {
- return null;
- }
- // We have to decorate here: if we let an asynchronous lightweight
- // decorator do it, image decorations may flicker in the
- // repositories view and elsewhere where we'd refresh viewers.
- return decorateImageDescriptor(base, node);
- }
-
- private ImageDescriptor getBaseImageDescriptor(
- @NonNull RepositoryTreeNode<?> node) {
switch (node.getType()) {
case FILE: {
Object item = node.getObject();
@@ -103,78 +86,6 @@ public class RepositoryTreeNodeWorkbenchAdapter extends WorkbenchAdapter {
return node.getType().getIcon();
}
- private ImageDescriptor decorateImageDescriptor(
- @NonNull ImageDescriptor base,
- @NonNull RepositoryTreeNode<?> node) {
- switch (node.getType()) {
- case TAG:
- case ADDITIONALREF:
- case REF:
- // if the branch or tag is checked out,
- // we want to decorate the corresponding
- // node with a little check indicator
- String refName = ((Ref) node.getObject()).getName();
- Ref leaf = ((Ref) node.getObject()).getLeaf();
-
- String compareString = null;
- Repository repository = node.getRepository();
- String branchName = DecoratorRepositoryStateCache.INSTANCE
- .getFullBranchName(repository);
- if (branchName == null) {
- return base;
- }
- if (refName.startsWith(Constants.R_HEADS)) {
- // local branch: HEAD would be on the branch
- compareString = refName;
- } else if (refName.startsWith(Constants.R_TAGS)) {
- // tag: HEAD would be on the commit id to which the tag is
- // pointing
- TagNode tagNode = (TagNode) node;
- compareString = tagNode.getCommitId();
- } else if (refName.startsWith(Constants.R_REMOTES)) {
- // remote branch: branch name is object id in detached HEAD
- // state
- ObjectId objectId = leaf.getObjectId();
- if (objectId != null) {
- String leafName = objectId.getName();
- if (leafName.equals(branchName)) {
- return new DecorationOverlayDescriptor(base,
- UIIcons.OVR_CHECKEDOUT, IDecoration.TOP_LEFT);
- }
- }
- } else if (refName.equals(Constants.HEAD)) {
- return new DecorationOverlayDescriptor(base,
- UIIcons.OVR_CHECKEDOUT, IDecoration.TOP_LEFT);
- } else {
- String leafname = leaf.getName();
- if (leafname.startsWith(Constants.R_REFS)
- && leafname.equals(branchName)) {
- return new DecorationOverlayDescriptor(base,
- UIIcons.OVR_CHECKEDOUT, IDecoration.TOP_LEFT);
- }
- ObjectId objectId = leaf.getObjectId();
- if (objectId != null && objectId
- .equals(DecoratorRepositoryStateCache.INSTANCE
- .getHead(repository))) {
- return new DecorationOverlayDescriptor(base,
- UIIcons.OVR_CHECKEDOUT, IDecoration.TOP_LEFT);
- }
- // some other symbolic reference
- return base;
- }
-
- if (compareString != null && compareString.equals(branchName)) {
- return new DecorationOverlayDescriptor(base,
- UIIcons.OVR_CHECKEDOUT, IDecoration.TOP_LEFT);
- }
-
- break;
- default:
- break;
- }
- return base;
- }
-
@Override
public String getLabel(Object object) {
RepositoryTreeNode<?> node = (RepositoryTreeNode) object;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/DeleteRepositoryGroupConfirmDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/DeleteRepositoryGroupConfirmDialog.java
index ae9d7a2b8..26d7030d1 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/DeleteRepositoryGroupConfirmDialog.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/DeleteRepositoryGroupConfirmDialog.java
@@ -77,7 +77,8 @@ public class DeleteRepositoryGroupConfirmDialog extends TitleAreaDialog {
SWT.BORDER | SWT.V_SCROLL);
GridDataFactory.fillDefaults().grab(true, true)
.applyTo(groupsViewer.getControl());
- groupsViewer.setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ groupsViewer
+ .setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
groupsViewer.setContentProvider(
new DeleteRepositoryGroupTreeContentProvider());
groupsViewer.setInput(groupsToDelete);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchPage.java
index 5f41929e3..f8c1ec790 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchPage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/search/CommitSearchPage.java
@@ -312,7 +312,7 @@ public class CommitSearchPage extends DialogPage implements ISearchPage {
repositoryGroup, SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL
| SWT.BORDER);
this.repositoryViewer
- .setLabelProvider(new RepositoryTreeNodeLabelProvider());
+ .setLabelProvider(new RepositoryTreeNodeLabelProvider(true));
this.repositoryViewer
.setContentProvider(new RepositoriesViewContentProvider());
this.repositoryViewer

Back to the top