Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.egit.ui/src/org/eclipse')
-rwxr-xr-xorg.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java567
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIUtils.java6
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java12
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java9
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/RepositoryLocationContentProvider.java6
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffRegionFormatter.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffViewer.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/RepositoryCommit.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CheckboxLabelProvider.java204
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ControlLabelProvider.java175
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java97
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitCombo.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitAndDiffComponent.java489
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java10
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarJob.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java314
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java19
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/SynchronizePreferencePage.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/EditableRevision.java215
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/LocationEditableRevision.java13
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/ResourceEditableRevision.java10
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingView.java34
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties5
34 files changed, 1181 insertions, 1053 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java
index 92f720629..a19ff49e7 100755
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java
@@ -20,9 +20,8 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
import java.util.Dictionary;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
@@ -30,22 +29,12 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Stream;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRunnable;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
@@ -53,8 +42,8 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.egit.core.JobFamilies;
import org.eclipse.egit.core.RepositoryCache;
import org.eclipse.egit.core.RepositoryUtil;
+import org.eclipse.egit.core.internal.ResourceRefreshHandler;
import org.eclipse.egit.core.internal.job.RuleUtil;
-import org.eclipse.egit.core.internal.util.ResourceUtil;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.internal.ConfigurationChecker;
import org.eclipse.egit.ui.internal.KnownHosts;
@@ -76,7 +65,6 @@ import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jgit.events.IndexChangedListener;
import org.eclipse.jgit.events.ListenerHandle;
import org.eclipse.jgit.events.WorkingTreeModifiedEvent;
-import org.eclipse.jgit.events.WorkingTreeModifiedListener;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.treewalk.FileTreeIterator;
@@ -327,8 +315,8 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
private ResourceManager resourceManager;
private RepositoryChangeScanner rcs;
+
private ResourceRefreshJob refreshJob;
- private ListenerHandle refreshHandle;
private DebugOptions debugOptions;
private volatile boolean uiIsActive;
@@ -358,7 +346,6 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
RepositoryStateCache.INSTANCE.initialize();
setupRepoChangeScanner();
- setupRepoIndexRefresh();
setupFocusHandling();
setupCredentialsProvider();
ConfigurationChecker.checkConfiguration();
@@ -460,7 +447,6 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
updateUiState();
// 500: give the UI task a chance to update the active state
rcs.schedule(500);
- refreshJob.triggerRefresh();
}
};
Job job = new Job(UIText.Activator_setupFocusListener) {
@@ -516,12 +502,6 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
return debugOptions;
}
- private void setupRepoIndexRefresh() {
- refreshJob = new ResourceRefreshJob();
- refreshHandle = Repository.getGlobalListenerList()
- .addWorkingTreeModifiedListener(refreshJob);
- }
-
/**
* Register for changes made to Team properties.
*
@@ -556,365 +536,6 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
}
/**
- * Refreshes parts of the workspace changed by JGit operations. This will
- * not refresh any git-ignored resources since those are not reported in the
- * {@link WorkingTreeModifiedEvent}.
- */
- static class ResourceRefreshJob extends Job implements
- WorkingTreeModifiedListener {
-
- ResourceRefreshJob() {
- super(UIText.Activator_refreshJobName);
- setUser(false);
- setSystem(true);
- }
-
- /**
- * Internal helper class to record batched accumulated results from
- * several {@link WorkingTreeModifiedEvent}s.
- */
- private static class WorkingTreeChanges {
-
- private final File workTree;
-
- private final Set<String> modified;
-
- private final Set<String> deleted;
-
- public WorkingTreeChanges(WorkingTreeModifiedEvent event) {
- workTree = event.getRepository().getWorkTree()
- .getAbsoluteFile();
- modified = new HashSet<>(event.getModified());
- deleted = new HashSet<>(event.getDeleted());
- }
-
- public File getWorkTree() {
- return workTree;
- }
-
- public Set<String> getModified() {
- return modified;
- }
-
- public Set<String> getDeleted() {
- return deleted;
- }
-
- public boolean isEmpty() {
- return modified.isEmpty() && deleted.isEmpty();
- }
-
- public WorkingTreeChanges merge(WorkingTreeModifiedEvent event) {
- modified.removeAll(event.getDeleted());
- deleted.removeAll(event.getModified());
- modified.addAll(event.getModified());
- deleted.addAll(event.getDeleted());
- return this;
- }
- }
-
- private Map<File, WorkingTreeChanges> repositoriesChanged = new LinkedHashMap<>();
-
- @Override
- public IStatus run(IProgressMonitor monitor) {
- try {
- List<WorkingTreeChanges> changes;
- synchronized (repositoriesChanged) {
- if (repositoriesChanged.isEmpty()) {
- return Status.OK_STATUS;
- }
- changes = new ArrayList<>(repositoriesChanged.values());
- repositoriesChanged.clear();
- }
-
- SubMonitor progress = SubMonitor.convert(monitor,
- changes.size());
- try {
- for (WorkingTreeChanges change : changes) {
- refreshRepository(change, progress.newChild(1));
- }
- } catch (OperationCanceledException oe) {
- return Status.CANCEL_STATUS;
- } catch (CoreException e) {
- handleError(UIText.Activator_refreshFailed, e, false);
- return new Status(IStatus.ERROR, getPluginId(),
- e.getMessage());
- }
-
- if (!monitor.isCanceled()) {
- // re-schedule if we got some changes in the meantime
- synchronized (repositoriesChanged) {
- if (!repositoriesChanged.isEmpty()) {
- schedule(100);
- }
- }
- }
- } finally {
- monitor.done();
- }
- return Status.OK_STATUS;
- }
-
- private void refreshRepository(WorkingTreeChanges changes,
- IProgressMonitor monitor) throws CoreException {
- if (monitor.isCanceled()) {
- throw new OperationCanceledException();
- }
- if (changes.isEmpty()) {
- return; // Should actually not occur
- }
- Map<IPath, IProject> roots = getProjectLocations(
- changes.getWorkTree());
- if (roots.isEmpty()) {
- // No open projects from this repository in the workspace
- return;
- }
- SubMonitor progress = SubMonitor.convert(monitor, 2);
- IPath workTree = new Path(changes.getWorkTree().getPath());
- Map<IResource, Boolean> toRefresh = computeResources(
- changes.getModified(), changes.getDeleted(), workTree,
- roots, progress.newChild(1));
- if (toRefresh.isEmpty()) {
- return;
- }
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- IWorkspaceRunnable operation = innerMonitor -> {
- SubMonitor innerProgress = SubMonitor.convert(innerMonitor,
- toRefresh.size());
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace()
- .trace(GitTraceLocation.REPOSITORYCHANGESCANNER
- .getLocation(),
- "Refreshing repository " + workTree + ' ' //$NON-NLS-1$
- + toRefresh.size());
- }
- for (Map.Entry<IResource, Boolean> entry : toRefresh
- .entrySet()) {
- entry.getKey().refreshLocal(entry.getValue().booleanValue()
- ? IResource.DEPTH_INFINITE : IResource.DEPTH_ONE,
- innerProgress.newChild(1));
- }
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace()
- .trace(GitTraceLocation.REPOSITORYCHANGESCANNER
- .getLocation(),
- "Refreshed repository " + workTree + ' ' //$NON-NLS-1$
- + toRefresh.size());
- }
- };
- // No scheduling rule needed; IResource.refreshLocal() gets its own
- // rule. This workspace operation serves only to batch resource
- // update notifications.
- workspace.run(operation, null, IWorkspace.AVOID_UPDATE,
- progress.newChild(1));
- }
-
- private Map<IPath, IProject> getProjectLocations(File workTree) {
- IProject[] projects = RuleUtil.getProjects(workTree);
- if (projects == null) {
- return Collections.emptyMap();
- }
- Map<IPath, IProject> result = new HashMap<>();
- for (IProject project : projects) {
- if (project.isAccessible()) {
- IPath path = project.getLocation();
- if (path != null) {
- IPath projectFilePath = path.append(
- IProjectDescription.DESCRIPTION_FILE_NAME);
- if (projectFilePath.toFile().exists()) {
- result.put(path, project);
- }
- }
- }
- }
- return result;
- }
-
- private Map<IResource, Boolean> computeResources(
- Set<String> modified, Set<String> deleted, IPath workTree,
- Map<IPath, IProject> roots, IProgressMonitor monitor) {
- // Attempt to minimize the refreshes by returning IContainers if
- // more than one file in a container has changed.
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace().trace(
- GitTraceLocation.REPOSITORYCHANGESCANNER.getLocation(),
- "Calculating refresh for repository " + workTree + ' ' //$NON-NLS-1$
- + modified.size() + ' ' + deleted.size());
- }
- SubMonitor progress = SubMonitor.convert(monitor,
- modified.size() + deleted.size());
- Set<IPath> fullRefreshes = new HashSet<>();
- Map<IPath, IFile> handled = new HashMap<>();
- Map<IResource, Boolean> result = new HashMap<>();
- Stream.concat(modified.stream(), deleted.stream()).forEach(path -> {
- if (progress.isCanceled()) {
- throw new OperationCanceledException();
- }
- IPath filePath = "/".equals(path) ? workTree //$NON-NLS-1$
- : workTree.append(path);
- IProject project = roots.get(filePath);
- if (project != null) {
- // Eclipse knows this as a project. Make sure it gets
- // refreshed as such. One can refresh a folder via an IFile,
- // but not an IProject.
- handled.put(filePath, null);
- result.put(project, Boolean.FALSE);
- progress.worked(1);
- return;
- }
- if (fullRefreshes.stream()
- .anyMatch(full -> full.isPrefixOf(filePath))
- || !roots.keySet().stream()
- .anyMatch(root -> root.isPrefixOf(filePath))) {
- // Not in workspace or covered by a full container refresh
- progress.worked(1);
- return;
- }
- IPath containerPath;
- boolean isFile;
- if (path.endsWith("/")) { //$NON-NLS-1$
- // It's already a directory
- isFile = false;
- containerPath = filePath.removeTrailingSeparator();
- } else {
- isFile = true;
- containerPath = filePath.removeLastSegments(1);
- }
- if (!handled.containsKey(containerPath)) {
- if (!isFile && containerPath != null) {
- IContainer container = ResourceUtil
- .getContainerForLocation(containerPath, false);
- if (container != null) {
- IFile file = handled.get(containerPath);
- handled.put(containerPath, null);
- if (file != null) {
- result.remove(file);
- }
- result.put(container, Boolean.FALSE);
- }
- } else if (isFile) {
- // First file in this container. Find the deepest
- // existing container and record its non-existing child.
- String lastPart = filePath.lastSegment();
- while (containerPath != null
- && workTree.isPrefixOf(containerPath)) {
- IContainer container = ResourceUtil
- .getContainerForLocation(containerPath,
- false);
- if (container == null) {
- lastPart = containerPath.lastSegment();
- containerPath = containerPath
- .removeLastSegments(1);
- isFile = false;
- continue;
- }
- if (container.getType() == IResource.ROOT) {
- // Missing project... ignore it and anything
- // beneath. The user or our own branch project
- // tracker will have to properly add/import the
- // project.
- containerPath = containerPath.append(lastPart);
- fullRefreshes.add(containerPath);
- handled.put(containerPath, null);
- } else if (isFile) {
- IFile file = container
- .getFile(new Path(lastPart));
- handled.put(containerPath, file);
- result.put(file, Boolean.FALSE);
- } else {
- // New or deleted folder.
- container = container
- .getFolder(new Path(lastPart));
- containerPath = containerPath.append(lastPart);
- fullRefreshes.add(containerPath);
- handled.put(containerPath, null);
- result.put(container, Boolean.TRUE);
- }
- break;
- }
- }
- } else {
- IFile file = handled.get(containerPath);
- if (file != null) {
- // Second file in this container: replace file by
- // its container.
- handled.put(containerPath, null);
- result.remove(file);
- result.put(file.getParent(), Boolean.FALSE);
- }
- // Otherwise we already have this container.
- }
- progress.worked(1);
- });
-
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace().trace(
- GitTraceLocation.REPOSITORYCHANGESCANNER.getLocation(),
- "Calculated refresh for repository " + workTree); //$NON-NLS-1$
- }
- return result;
- }
-
- @Override
- public void onWorkingTreeModified(WorkingTreeModifiedEvent event) {
- if (Activator.getDefault().getPreferenceStore()
- .getBoolean(UIPreferences.REFRESH_ON_INDEX_CHANGE)) {
- mayTriggerRefresh(event);
- }
- }
-
- /**
- * Record which projects have changes. Initiate a resource refresh job
- * if the user settings allow it.
- *
- * @param event
- * The {@link WorkingTreeModifiedEvent} that triggered this
- * refresh
- */
- private void mayTriggerRefresh(WorkingTreeModifiedEvent event) {
- if (event.isEmpty()) {
- return;
- }
- Repository repo = event.getRepository();
- if (repo == null || repo.isBare()) {
- return; // Should never occur
- }
- File gitDir = repo.getDirectory();
- synchronized (repositoriesChanged) {
- WorkingTreeChanges changes = repositoriesChanged.get(gitDir);
- if (changes == null) {
- repositoriesChanged.put(gitDir,
- new WorkingTreeChanges(event));
- } else {
- changes.merge(event);
- if (changes.isEmpty()) {
- // Actually, this cannot happen.
- repositoriesChanged.remove(gitDir);
- }
- }
- }
- if (!Activator.getDefault().getPreferenceStore()
- .getBoolean(UIPreferences.REFRESH_ONLY_WHEN_ACTIVE)
- || isActive()) {
- triggerRefresh();
- }
- }
-
- /**
- * Figure which projects belong to a repository, add them to a set of
- * project to refresh and schedule the refresh as a job.
- */
- void triggerRefresh() {
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace().trace(
- GitTraceLocation.REPOSITORYCHANGESCANNER.getLocation(),
- "Triggered refresh"); //$NON-NLS-1$
- }
- schedule();
- }
- }
-
- /**
* A Job that looks at the repository meta data and triggers a refresh of
* the resources in the affected projects.
*/
@@ -926,8 +547,12 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
private int interval;
+ private final ResourceRefreshJob refresher;
+
private final RepositoryCache repositoryCache;
+ private Collection<WorkingTreeModifiedEvent> events;
+
private final IndexChangedListener listener = event -> {
if (event.isInternal()) {
return;
@@ -992,12 +617,15 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
if (directories.isEmpty()) {
return;
}
- repository
- .fireEvent(new WorkingTreeModifiedEvent(directories, null));
+ WorkingTreeModifiedEvent evt = new WorkingTreeModifiedEvent(
+ directories, null);
+ evt.setRepository(repository);
+ events.add(evt);
};
- RepositoryChangeScanner() {
+ public RepositoryChangeScanner(ResourceRefreshJob refresher) {
super(UIText.Activator_repoScanJobName);
+ this.refresher = refresher;
setRule(new RepositoryCacheRule());
setSystem(true);
setUser(false);
@@ -1016,7 +644,7 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
return doReschedule;
}
- void setReschedule(boolean reschedule){
+ public void setReschedule(boolean reschedule) {
doReschedule = reschedule;
}
@@ -1040,6 +668,7 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
monitor.beginTask(UIText.Activator_scanningRepositories,
repos.length);
try {
+ events = new ArrayList<>();
for (Repository repo : repos) {
if (monitor.isCanceled()) {
break;
@@ -1067,12 +696,16 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
}
monitor.worked(1);
}
+ if (!monitor.isCanceled()) {
+ refresher.trigger(events);
+ }
+ events.clear();
} catch (IOException e) {
if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
GitTraceLocation.getTrace().trace(
GitTraceLocation.REPOSITORYCHANGESCANNER
.getLocation(),
- "Stopped rescheduling " + getName() + "job"); //$NON-NLS-1$ //$NON-NLS-2$
+ "Stopped rescheduling " + getName() + " job"); //$NON-NLS-1$ //$NON-NLS-2$
}
return createErrorStatus(UIText.Activator_scanError, e);
} finally {
@@ -1113,18 +746,161 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
}
}
+ /**
+ * Refreshes parts of the workspace changed by JGit operations. This will
+ * not refresh any git-ignored resources since those are not reported in the
+ * {@link WorkingTreeModifiedEvent}.
+ */
+ private static class ResourceRefreshJob extends Job {
+
+ public ResourceRefreshJob() {
+ super(UIText.Activator_refreshJobName);
+ setUser(false);
+ setSystem(true);
+ }
+
+ /**
+ * Internal helper class to record batched accumulated results from
+ * several {@link WorkingTreeModifiedEvent}s.
+ */
+ private static class WorkingTreeChanges {
+
+ private final File workTree;
+
+ private final Set<String> modified;
+
+ private final Set<String> deleted;
+
+ public WorkingTreeChanges(WorkingTreeModifiedEvent event) {
+ workTree = event.getRepository().getWorkTree()
+ .getAbsoluteFile();
+ modified = new HashSet<>(event.getModified());
+ deleted = new HashSet<>(event.getDeleted());
+ }
+
+ public File getWorkTree() {
+ return workTree;
+ }
+
+ public Set<String> getModified() {
+ return modified;
+ }
+
+ public Set<String> getDeleted() {
+ return deleted;
+ }
+
+ public boolean isEmpty() {
+ return modified.isEmpty() && deleted.isEmpty();
+ }
+
+ public WorkingTreeChanges merge(WorkingTreeModifiedEvent event) {
+ modified.removeAll(event.getDeleted());
+ deleted.removeAll(event.getModified());
+ modified.addAll(event.getModified());
+ deleted.addAll(event.getDeleted());
+ return this;
+ }
+ }
+
+ private Map<File, WorkingTreeChanges> repositoriesChanged = new LinkedHashMap<>();
+
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ try {
+ List<WorkingTreeChanges> changes;
+ synchronized (repositoriesChanged) {
+ if (repositoriesChanged.isEmpty()) {
+ return Status.OK_STATUS;
+ }
+ changes = new ArrayList<>(repositoriesChanged.values());
+ repositoriesChanged.clear();
+ }
+
+ SubMonitor progress = SubMonitor.convert(monitor,
+ changes.size());
+ try {
+ for (WorkingTreeChanges change : changes) {
+ if (progress.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ ResourceRefreshHandler handler = new ResourceRefreshHandler();
+ handler.refreshRepository(new WorkingTreeModifiedEvent(
+ change.getModified(), change.getDeleted()),
+ change.getWorkTree(), progress.newChild(1));
+ }
+ } catch (OperationCanceledException oe) {
+ return Status.CANCEL_STATUS;
+ } catch (CoreException e) {
+ handleError(UIText.Activator_refreshFailed, e, false);
+ return new Status(IStatus.ERROR, getPluginId(),
+ e.getMessage());
+ }
+
+ if (!monitor.isCanceled()) {
+ // re-schedule if we got some changes in the meantime
+ synchronized (repositoriesChanged) {
+ if (!repositoriesChanged.isEmpty()) {
+ schedule(100);
+ }
+ }
+ }
+ } finally {
+ monitor.done();
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Record which projects have changes. Initiate a resource refresh job
+ * if the user settings allow it.
+ *
+ * @param events
+ * The {@link WorkingTreeModifiedEvent}s that triggered this
+ * refresh
+ */
+ public void trigger(Collection<WorkingTreeModifiedEvent> events) {
+ boolean haveChanges = false;
+ for (WorkingTreeModifiedEvent event : events) {
+ if (event.isEmpty()) {
+ continue;
+ }
+ Repository repo = event.getRepository();
+ if (repo == null || repo.isBare()) {
+ continue; // Should never occur
+ }
+ File gitDir = repo.getDirectory();
+ synchronized (repositoriesChanged) {
+ WorkingTreeChanges changes = repositoriesChanged
+ .get(gitDir);
+ if (changes == null) {
+ repositoriesChanged.put(gitDir,
+ new WorkingTreeChanges(event));
+ } else {
+ changes.merge(event);
+ if (changes.isEmpty()) {
+ // Actually, this cannot happen.
+ repositoriesChanged.remove(gitDir);
+ }
+ }
+ }
+ haveChanges = true;
+ }
+ if (haveChanges) {
+ schedule();
+ }
+ }
+ }
+
private void setupRepoChangeScanner() {
- rcs = new RepositoryChangeScanner();
+ refreshJob = new ResourceRefreshJob();
+ rcs = new RepositoryChangeScanner(refreshJob);
getPreferenceStore().addPropertyChangeListener(rcs);
}
@Override
public void stop(final BundleContext context) throws Exception {
RepositoryStateCache.INSTANCE.dispose();
- if (refreshHandle != null) {
- refreshHandle.remove();
- refreshHandle = null;
- }
if (focusListener != null) {
if (PlatformUI.isWorkbenchRunning()) {
@@ -1142,21 +918,16 @@ public class Activator extends AbstractUIPlugin implements DebugOptionsListener
getPreferenceStore().removePropertyChangeListener(rcs);
rcs.setReschedule(false);
rcs.cancel();
- if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
- GitTraceLocation.getTrace().trace(
- GitTraceLocation.REPOSITORYCHANGESCANNER.getLocation(),
- "Trying to cancel " + refreshJob.getName() + " job"); //$NON-NLS-1$ //$NON-NLS-2$
- }
refreshJob.cancel();
rcs.join();
refreshJob.join();
-
if (GitTraceLocation.REPOSITORYCHANGESCANNER.isActive()) {
GitTraceLocation.getTrace().trace(
GitTraceLocation.REPOSITORYCHANGESCANNER.getLocation(),
"Jobs terminated"); //$NON-NLS-1$
}
+
if (resourceManager != null) {
resourceManager.dispose();
resourceManager = null;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIUtils.java
index 89922c017..0cdd39750 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIUtils.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIUtils.java
@@ -445,8 +445,7 @@ public class UIUtils {
resultList.add(propsal);
}
}
- return resultList.toArray(new IContentProposal[resultList
- .size()]);
+ return resultList.toArray(new IContentProposal[0]);
}
};
@@ -597,8 +596,7 @@ public class UIUtils {
resultList.add(proposal);
}
}
- return resultList.toArray(new IContentProposal[resultList
- .size()]);
+ return resultList.toArray(new IContentProposal[0]);
}
};
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
index eeb02c6ba..e9dbb0add 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
@@ -1111,9 +1111,9 @@ public class CompareUtils {
@Override
public void apply(DirCacheEntry ent) {
ObjectInserter inserter = repo.newObjectInserter();
- if (ent.getFileMode() != FileMode.REGULAR_FILE)
+ if ((ent.getRawMode() & FileMode.TYPE_MASK) != FileMode.TYPE_FILE) {
ent.setFileMode(FileMode.REGULAR_FILE);
-
+ }
ent.setLength(content.limit());
ent.setLastModified(Instant.now());
try {
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 f1b6d24c4..54b38699c 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
@@ -102,14 +102,6 @@ public class UIIcons {
/** Filter icon */
public final static ImageDescriptor ELCL16_COLUMN_LAYOUT;
- /** Enabled, checked, checkbox image */
- public final static ImageDescriptor CHECKBOX_ENABLED_CHECKED;
- /** Enabled, unchecked, checkbox image */
- public final static ImageDescriptor CHECKBOX_ENABLED_UNCHECKED;
- /** Disabled, checked, checkbox image */
- public final static ImageDescriptor CHECKBOX_DISABLED_CHECKED;
- /** Disabled, unchecked, checkbox image */
- public final static ImageDescriptor CHECKBOX_DISABLED_UNCHECKED;
/** Edit configuration */
public final static ImageDescriptor EDITCONFIG;
/** Create Patch Wizard banner */
@@ -409,10 +401,6 @@ public class UIIcons {
ELCL16_SYNCED = map("elcl16/synced.png"); //$NON-NLS-1$
ELCL16_ID = map("elcl16/sha1.png"); //$NON-NLS-1$
ELCL16_COLUMN_LAYOUT = map("elcl16/horizontal_view.png"); //$NON-NLS-1$
- CHECKBOX_ENABLED_CHECKED = map("checkboxes/enabled_checked.png"); //$NON-NLS-1$
- CHECKBOX_ENABLED_UNCHECKED = map("checkboxes/enabled_unchecked.png"); //$NON-NLS-1$
- CHECKBOX_DISABLED_CHECKED = map("checkboxes/disabled_checked.png"); //$NON-NLS-1$
- CHECKBOX_DISABLED_UNCHECKED = map("checkboxes/disabled_unchecked.png"); //$NON-NLS-1$
// Eclipse 4.14 has a new filter icon showing a funnel.
if (Platform.getBundle("org.eclipse.ui.ide").getVersion() //$NON-NLS-1$
.compareTo(Version.valueOf("3.16.100")) >= 0) { //$NON-NLS-1$
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 394df7030..a37cc913c 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
@@ -694,6 +694,12 @@ public class UIText extends NLS {
public static String GitPreferenceRoot_DefaultRepoFolderVariableButton;
/** */
+ public static String GitPreferenceRoot_HttpClient_Jdk_Label;
+
+ /** */
+ public static String GitPreferenceRoot_HttpClient_Apache_Label;
+
+ /** */
public static String GitPreferenceRoot_MergeGroupHeader;
/** */
@@ -4892,6 +4898,9 @@ public class UIText extends NLS {
public static String GitPreferenceRoot_MaxPullThreadsCountTooltip;
/** */
+ public static String RemoteConnectionPreferencePage_HttpClientLabel;
+
+ /** */
public static String RemoteConnectionPreferencePage_SshClientLabel;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java
index 78c1f11fb..166b5c68d 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitActionHandler.java
@@ -151,8 +151,7 @@ public class CommitActionHandler extends RepositoryActionHandler {
result[0] = new IndexDiffData(
CommitUI.getIndexDiff(repository,
projects.toArray(
- new IProject[projects
- .size()]),
+ new IProject[0]),
monitor));
} catch (IOException e) {
throw new InvocationTargetException(e);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/RepositoryLocationContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/RepositoryLocationContentProvider.java
index 17fbdaf0f..f589afbeb 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/RepositoryLocationContentProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/RepositoryLocationContentProvider.java
@@ -57,8 +57,7 @@ class RepositoryLocationContentProvider implements ITreeContentProvider {
@SuppressWarnings("unchecked")
public Object[] getElements(Object inputElement) {
List<CloneSourceProvider> repositoryImports = (List<CloneSourceProvider>) inputElement;
- return repositoryImports.toArray(new CloneSourceProvider[repositoryImports
- .size()]);
+ return repositoryImports.toArray(new CloneSourceProvider[0]);
}
@Override
@@ -76,8 +75,7 @@ class RepositoryLocationContentProvider implements ITreeContentProvider {
return null;
cacheParents(repositoryImport, repositoryServerInfos);
return repositoryServerInfos
- .toArray(new RepositoryServerInfo[repositoryServerInfos
- .size()]);
+ .toArray(new RepositoryServerInfo[0]);
}
return null;
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffRegionFormatter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffRegionFormatter.java
index 84a331ac5..0631ed12e 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffRegionFormatter.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffRegionFormatter.java
@@ -322,7 +322,7 @@ public class DiffRegionFormatter extends DiffFormatter {
* @return non-null but possibly empty array
*/
public DiffRegion[] getRegions() {
- return this.regions.toArray(new DiffRegion[this.regions.size()]);
+ return this.regions.toArray(new DiffRegion[0]);
}
/**
@@ -332,7 +332,7 @@ public class DiffRegionFormatter extends DiffFormatter {
*/
public FileDiffRegion[] getFileRegions() {
return this.fileRegions
- .toArray(new FileDiffRegion[this.fileRegions.size()]);
+ .toArray(new FileDiffRegion[0]);
}
/**
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffViewer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffViewer.java
index fce1d1292..acdb79755 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffViewer.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commit/DiffViewer.java
@@ -169,7 +169,7 @@ public class DiffViewer extends HyperlinkSourceViewer {
Assert.isTrue(sourceViewer instanceof DiffViewer);
DiffViewer viewer = (DiffViewer) sourceViewer;
return viewer.tokens.keySet()
- .toArray(new String[viewer.tokens.size()]);
+ .toArray(new String[0]);
}
@Override
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 8cd37fff5..5fd6f5206 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
@@ -207,8 +207,7 @@ public class RepositoryCommit extends WorkbenchAdapter
if (note != null)
noteList.add(new RepositoryCommitNote(this, ref, note));
}
- notes = noteList.toArray(new RepositoryCommitNote[noteList
- .size()]);
+ notes = noteList.toArray(new RepositoryCommitNote[0]);
} catch (Exception e) {
Activator.logError("Error showing notes", e); //$NON-NLS-1$
notes = new RepositoryCommitNote[0];
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CheckboxLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CheckboxLabelProvider.java
deleted file mode 100644
index f4f7a88ae..000000000
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CheckboxLabelProvider.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * Copyright (C) 2011, Dariusz Luksza <dariusz.luksza@gmail.com>
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *******************************************************************************/
-package org.eclipse.egit.ui.internal.components;
-
-import static org.eclipse.jface.resource.ImageDescriptor.createFromImageData;
-import static org.eclipse.jface.resource.JFaceResources.getResources;
-
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.egit.ui.internal.UIIcons;
-import org.eclipse.jface.resource.LocalResourceManager;
-import org.eclipse.jface.resource.ResourceManager;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.RGB;
-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.Shell;
-
-/**
- * Label provider displaying native check boxes images for boolean values.
- * Label-image is centralized.
- * <p>
- * Concrete implementations must provide object to boolean mapping.
- * <p>
- * This implementation is actually workaround for lacking features in
- * TableViewer. It is based on (workaround) snippets&tricks found on Internet.
- */
-public abstract class CheckboxLabelProvider extends CenteredImageLabelProvider {
-
- private static class CheckBoxImages {
- private final Image checkedEnabled;
-
- private final Image uncheckedEnabled;
-
- private final Image checkedDisabled;
-
- private final Image uncheckedDisabled;
-
- public CheckBoxImages(Image checkedEnabled, Image uncheckedEnabled,
- Image checkedDisabled, Image uncheckedDisabled) {
- this.checkedEnabled = checkedEnabled;
- this.uncheckedEnabled = uncheckedEnabled;
- this.checkedDisabled = checkedDisabled;
- this.uncheckedDisabled = uncheckedDisabled;
- }
-
- }
-
- private final CheckBoxImages checkBoxes;
-
- private final LocalResourceManager resourceManager;
-
- private static CheckBoxImages createCheckboxImage(
- ResourceManager resourceManager, Control control) {
-
- String checkboxhack = System.getProperty("egit.swt.checkboxhack"); //$NON-NLS-1$
- if (checkboxhack == null)
- if (Platform.getOS().equals(Platform.OS_MACOSX))
- checkboxhack = "hardwired"; //$NON-NLS-1$
- else
- checkboxhack = "screenshot"; //$NON-NLS-1$
-
- if ("hardwired".equals(checkboxhack)) //$NON-NLS-1$
- return new CheckBoxImages(
- UIIcons.CHECKBOX_ENABLED_CHECKED.createImage(),
- UIIcons.CHECKBOX_ENABLED_UNCHECKED.createImage(),
- UIIcons.CHECKBOX_DISABLED_CHECKED.createImage(),
- UIIcons.CHECKBOX_DISABLED_UNCHECKED.createImage());
-
- Shell shell = new Shell(control.getShell(), SWT.NO_TRIM);
- // Hopefully no platform uses exactly this color because we'll make
- // it transparent in the image.
- Color gray = resourceManager.createColor(new RGB(222, 223, 224));
-
- Composite composite = new Composite(shell, SWT.NONE);
- RowLayout layout = new RowLayout();
- layout.marginTop = 0;
- layout.marginLeft = 0;
- layout.marginBottom = 0;
- layout.marginRight = 0;
- layout.spacing = 0;
- composite.setLayout(layout);
- createButton(composite, gray, true, true);
- createButton(composite, gray, false, true);
- createButton(composite, gray, true, false);
- createButton(composite, gray, false, false);
-
- Point cSize = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- composite.setSize(cSize);
- shell.setBackground(gray);
- shell.setLocation(0, 0);
- shell.setSize(cSize);
-
- Display display = shell.getShell().getDisplay();
-
- shell.open();
- Image canvas = new Image(display, cSize.x, cSize.y);
- GC gc = new GC(canvas);
- composite.print(gc);
-
- int buttonX = cSize.x / 4;
- Image[] images = new Image[4];
-
- for (int i = 0; i < 4; i++) {
- Image image = new Image(display, buttonX, cSize.y);
- gc.copyArea(image, buttonX * i, 0);
- images[i] = getImage(resourceManager, gray, image);
- }
-
- canvas.dispose();
- gc.dispose();
- shell.close();
-
- return new CheckBoxImages(images[0], images[1], images[2], images[3]);
- }
-
- private static void createButton(Composite parent, Color bgColor,
- boolean checked, boolean enabled) {
- Button button = new Button(parent, SWT.CHECK);
- button.setSelection(checked);
- button.setEnabled(enabled);
- button.setBackground(bgColor);
- Point bSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
- button.setSize(bSize);
- }
-
- private static Image getImage(ResourceManager rm, Color bgColor, Image img) {
- ImageData imageData = img.getImageData();
- imageData.transparentPixel = imageData.palette.getPixel(bgColor
- .getRGB());
- Image image = rm.createImage(createFromImageData(imageData));
- img.dispose();
-
- return image;
- }
-
- /**
- * Create label provider for provided viewer.
- *
- * @param control
- * viewer where label provided is used.
- */
- public CheckboxLabelProvider(final Control control) {
- resourceManager = new LocalResourceManager(getResources());
- checkBoxes = createCheckboxImage(resourceManager, control);
- }
-
- @Override
- protected Image getImage(final Object element) {
- if (isEnabled(element)) {
- if (isChecked(element))
- return checkBoxes.checkedEnabled;
-
- return checkBoxes.uncheckedEnabled;
- } else {
- if (isChecked(element))
- return checkBoxes.checkedDisabled;
-
- return checkBoxes.uncheckedDisabled;
- }
- }
-
- @Override
- public void dispose() {
- resourceManager.dispose();
- super.dispose();
- }
-
- /**
- * @param element
- * element to provide label for.
- * @return true if checkbox label should be checked for this element, false
- * otherwise.
- */
- protected abstract boolean isChecked(Object element);
-
- /**
- * Default implementation always return true.
- *
- * @param element
- * element to provide label for.
- * @return true if checkbox label should be enabled for this element, false
- * otherwise.
- */
- protected boolean isEnabled(final Object element) {
- return true;
- }
-}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ControlLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ControlLabelProvider.java
new file mode 100644
index 000000000..9806e06fb
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ControlLabelProvider.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Thomas Wolf <thomas.wolf@paranor.ch>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.components;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.util.Util;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Specialized label provider to put native SWT {@link Control}s into a column
+ * of a JFace {@link org.eclipse.jface.viewers.TableViewer TableViewer}.
+ */
+public abstract class ControlLabelProvider extends ColumnLabelProvider {
+
+ private final Map<TableItem, Editor> editors = new HashMap<>();
+
+ @Override
+ public void dispose() {
+ editors.clear();
+ super.dispose();
+ }
+
+ @Override
+ public String getText(Object element) {
+ return null;
+ }
+
+ @Override
+ public void update(ViewerCell cell) {
+ super.update(cell);
+ Object obj = cell.getElement();
+ Widget w = cell.getViewerRow().getItem();
+ if (w instanceof TableItem) {
+ TableItem item = (TableItem) w;
+ Table table = item.getParent();
+ Editor editor = editors.get(item);
+ if (editor == null) {
+ Control control = setEditor(cell, table, null, obj);
+ if (control == null) {
+ return;
+ }
+ control.pack();
+ editor = new Editor(table);
+ editor.horizontalAlignment = SWT.CENTER;
+ editor.verticalAlignment = SWT.CENTER;
+ Point size = control.getSize();
+ editor.minimumWidth = size.x;
+ editor.minimumHeight = size.y;
+ editors.put(item, editor);
+ editor.setEditor(control, item, cell.getColumnIndex());
+ editor.connect();
+ } else {
+ Control existing = editor.getEditor();
+ Control control = setEditor(cell, table, existing, obj);
+ if (control != existing) {
+ if (!existing.isDisposed()) {
+ existing.dispose();
+ }
+ if (control == null) {
+ editor.dispose();
+ return;
+ }
+ control.pack();
+ editor.setEditor(control);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates a new {@link Control}, or updates an existing one.
+ *
+ * @param cell
+ * that is being dealt with
+ * @param parent
+ * to use if a new control is created
+ * @param control
+ * an already existing widget to be updated, or {@code null} if a
+ * new widget should be created
+ * @param element
+ * being shown
+ * @return the {@link Control} to show, or {@code null} if no control is to
+ * be shown.
+ */
+ public abstract Control setEditor(ViewerCell cell, Composite parent,
+ Control control, Object element);
+
+ private class Editor extends TableEditor {
+
+ private DisposeListener disposer;
+
+ private final Table table;
+
+ public Editor(Table table) {
+ super(table);
+ this.table = table;
+ }
+
+ @Override
+ public void layout() {
+ if (Util.isGtk() && SWT.getVersion() <= 4924) {
+ // Layout is relative to the table's clientArea, which includes
+ // the header if one is shown. Results in editors being shown
+ // over the column headers.
+ //
+ // This is a work-around for bug 535978; would be needed only on
+ // SWT versions < 4924r7.
+ TableItem item = getItem();
+ if (item != null) {
+ Rectangle rect = item.getBounds();
+ if (table.getHeaderVisible()) {
+ Control editor = getEditor();
+ if (editor != null && !editor.isDisposed()) {
+ editor.setVisible(
+ rect.y >= table.getHeaderHeight());
+ }
+ }
+ }
+ }
+ super.layout();
+ }
+
+ public void connect() {
+ TableItem item = getItem();
+ if (item != null) {
+ disposer = e -> {
+ Control editor = getEditor();
+ if (editor != null && !editor.isDisposed()) {
+ editor.dispose();
+ }
+ dispose();
+ };
+ item.addDisposeListener(disposer);
+ }
+ }
+
+ private void disconnect() {
+ if (disposer != null) {
+ TableItem item = getItem();
+ if (item != null) {
+ editors.remove(item);
+ item.removeDisposeListener(disposer);
+ }
+ disposer = null;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ disconnect();
+ super.dispose();
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java
index b2d2cb3f7..26affb4a0 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java
@@ -40,6 +40,7 @@ import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
@@ -48,9 +49,12 @@ import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IElementComparer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -237,8 +241,6 @@ public class RefSpecPanel {
private CellEditor remoteRefCellEditor;
- private CellEditor forceUpdateCellEditor;
-
private CellEditor removeSpecCellEditor;
private int srcColumnIndex;
@@ -1182,53 +1184,67 @@ public class RefSpecPanel {
final TableViewerColumn column = createColumn(columnLayout,
UIText.RefSpecPanel_columnForce, COLUMN_FORCE_WEIGHT,
SWT.CENTER);
- column.setLabelProvider(new CheckboxLabelProvider(tableViewer
- .getControl()) {
- @Override
- protected boolean isChecked(final Object element) {
- return ((RefSpec) element).isForceUpdate();
- }
+ column.setLabelProvider(new ControlLabelProvider() {
@Override
- protected boolean isEnabled(Object element) {
- return !isDeleteRefSpec(element);
+ public Control setEditor(ViewerCell cell, Composite parent,
+ Control existing, Object element) {
+ Button editor;
+ if (existing != null) {
+ editor = (Button) existing;
+ } else {
+ editor = new Button(parent, SWT.CHECK);
+ editor.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Button b = (Button) e.getSource();
+ RefSpec oldSpec = (RefSpec) b.getData();
+ RefSpec newSpec = oldSpec
+ .setForceUpdate(b.getSelection());
+ setRefSpec(oldSpec, newSpec);
+ tableViewer.setSelection(
+ new StructuredSelection(newSpec), false);
+ }
+ });
+ if (Util.isWindows()) {
+ // Work-around for a rendering bug on Windows: the area
+ // above and below the checkbox is not redrawn when the
+ // selection changes.
+ ISelectionChangedListener listener = event -> {
+ if (!editor.isDisposed()) {
+ editor.redraw();
+ }
+ };
+ tableViewer.addSelectionChangedListener(listener);
+ editor.addDisposeListener(event -> tableViewer
+ .removeSelectionChangedListener(listener));
+ }
+ }
+ boolean isDeletion = isDeleteRefSpec(element);
+ editor.setData(element);
+ editor.setEnabled(!isDeletion);
+ editor.setSelection(
+ ((RefSpec) element).isForceUpdate() || isDeletion);
+ return editor;
}
@Override
public String getToolTipText(Object element) {
- if (!isEnabled(element))
- return UIText.RefSpecPanel_forceDeleteDescription;
- if (isChecked(element))
- return UIText.RefSpecPanel_forceTrueDescription + '\n'
+ if (element instanceof RefSpec) {
+ RefSpec refSpec = (RefSpec) element;
+ if (isDeleteRefSpec(refSpec)) {
+ return UIText.RefSpecPanel_forceDeleteDescription;
+ } else if (refSpec.isForceUpdate()) {
+ return UIText.RefSpecPanel_forceTrueDescription + '\n'
+ + UIText.RefSpecPanel_clickToChange;
+ }
+ return UIText.RefSpecPanel_forceFalseDescription + '\n'
+ UIText.RefSpecPanel_clickToChange;
- return UIText.RefSpecPanel_forceFalseDescription + '\n'
- + UIText.RefSpecPanel_clickToChange;
- }
- });
- column.setEditingSupport(new EditingSupport(tableViewer) {
- @Override
- protected boolean canEdit(final Object element) {
- return !isDeleteRefSpec(element);
- }
-
- @Override
- protected CellEditor getCellEditor(final Object element) {
- return forceUpdateCellEditor;
- }
-
- @SuppressWarnings("boxing")
- @Override
- protected Object getValue(final Object element) {
- return ((RefSpec) element).isForceUpdate();
+ }
+ return null;
}
- @SuppressWarnings("boxing")
- @Override
- protected void setValue(final Object element, final Object value) {
- final RefSpec oldSpec = (RefSpec) element;
- final RefSpec newSpec = oldSpec.setForceUpdate((Boolean) value);
- setRefSpec(oldSpec, newSpec);
- }
});
}
@@ -1287,7 +1303,6 @@ public class RefSpecPanel {
modeCellEditor = new CheckboxCellEditor(table);
localRefCellEditor = createLocalRefCellEditor(table);
remoteRefCellEditor = createRemoteRefCellEditor(table);
- forceUpdateCellEditor = new CheckboxCellEditor(table);
removeSpecCellEditor = new ClickableCellEditor(table);
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitCombo.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitCombo.java
index a14d3c691..1615b2f96 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitCombo.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitCombo.java
@@ -75,7 +75,7 @@ public class CommitCombo extends Composite {
list.add(makeContentProposal(message));
}
}
- return list.toArray(new IContentProposal[] {});
+ return list.toArray(new IContentProposal[0]);
}
/*
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitAndDiffComponent.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitAndDiffComponent.java
new file mode 100644
index 000000000..cb3fc091f
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitAndDiffComponent.java
@@ -0,0 +1,489 @@
+/*******************************************************************************
+ * Copyright (C) 2019 Thomas Wolf <thomas.wolf@paranor.ch>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.history;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.egit.ui.internal.ActionUtils;
+import org.eclipse.egit.ui.internal.commit.DiffViewer;
+import org.eclipse.egit.ui.internal.dialogs.HyperlinkSourceViewer;
+import org.eclipse.egit.ui.internal.dialogs.HyperlinkTokenScanner;
+import org.eclipse.egit.ui.internal.dialogs.ShowWhitespaceAction;
+import org.eclipse.egit.ui.internal.trace.GitTraceLocation;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.EditorsUI;
+
+/**
+ * A scrollable component that provides combined scrolling over two vertically
+ * arranged {@link StyledText}s, a {@link CommitMessageViewer} and a
+ * {@link DiffViewer}.
+ */
+public class CommitAndDiffComponent {
+
+ private ScrolledComposite commentAndDiffScrolledComposite;
+
+ private Composite commentAndDiffComposite;
+
+ /** Viewer displaying the currently selected commit. */
+ private CommitMessageViewer commentViewer;
+
+ /** Viewer displaying a unified diff of selected files from the commit. */
+ private DiffViewer diffViewer;
+
+ /** Remember caret positions; x = line, y = global offset. */
+ private Point commentCaret = new Point(0, 0);
+
+ private Point diffCaret = new Point(0, 0);
+
+ /** True during {@link #resizeCommentAndDiffScrolledComposite()}. */
+ private volatile boolean resizing;
+
+ /**
+ * Creates a new {@link CommitAndDiffComponent}.
+ *
+ * @param parent
+ * widget to use as parent
+ * @param site
+ * of the workbench part
+ */
+ public CommitAndDiffComponent(Composite parent, IWorkbenchPartSite site) {
+ commentAndDiffScrolledComposite = new ScrolledComposite(parent,
+ SWT.H_SCROLL | SWT.V_SCROLL);
+ commentAndDiffScrolledComposite.setExpandHorizontal(true);
+ commentAndDiffScrolledComposite.setExpandVertical(true);
+
+ commentAndDiffComposite = new Composite(commentAndDiffScrolledComposite,
+ SWT.NONE);
+ commentAndDiffScrolledComposite.setContent(commentAndDiffComposite);
+ commentAndDiffComposite
+ .setLayout(GridLayoutFactory.fillDefaults().create());
+
+ commentViewer = new CommitMessageViewer(commentAndDiffComposite, site);
+ commentViewer.getControl().setLayoutData(
+ GridDataFactory.fillDefaults().grab(true, false).create());
+
+ commentViewer.addTextInputListener(new ITextInputListener() {
+
+ @Override
+ public void inputDocumentChanged(IDocument oldInput,
+ IDocument newInput) {
+ commentCaret = new Point(0, 0);
+ }
+
+ @Override
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ // Nothing
+ }
+ });
+ commentViewer.addTextListener(
+ event -> resizeCommentAndDiffScrolledComposite());
+
+ StyledText commentWidget = commentViewer.getTextWidget();
+ commentWidget.addVerifyKeyListener(event -> {
+ // Get the current caret position *before* it moves (if it does)
+ int offset = commentWidget.getCaretOffset();
+ commentCaret = new Point(commentWidget.getLineAtOffset(offset),
+ offset);
+ });
+ commentWidget.addCaretListener(event -> {
+ Point location = commentWidget
+ .getLocationAtOffset(event.caretOffset);
+ scrollCommentAndDiff(location,
+ commentWidget.getLineHeight(event.caretOffset));
+ });
+
+ commentAndDiffComposite
+ .setBackground(commentViewer.getControl().getBackground());
+
+ HyperlinkSourceViewer.Configuration configuration = new HyperlinkSourceViewer.Configuration(
+ EditorsUI.getPreferenceStore()) {
+
+ @Override
+ public int getHyperlinkStateMask(ISourceViewer sourceViewer) {
+ return SWT.NONE;
+ }
+
+ @Override
+ protected IHyperlinkDetector[] internalGetHyperlinkDetectors(
+ ISourceViewer sourceViewer) {
+ IHyperlinkDetector[] registered = super.internalGetHyperlinkDetectors(
+ sourceViewer);
+ // Always add our special detector for commit hyperlinks; we
+ // want those to show always.
+ if (registered == null) {
+ return new IHyperlinkDetector[] {
+ new CommitMessageViewer.KnownHyperlinksDetector() };
+ } else {
+ IHyperlinkDetector[] result = new IHyperlinkDetector[registered.length
+ + 1];
+ System.arraycopy(registered, 0, result, 0,
+ registered.length);
+ result[registered.length] = new CommitMessageViewer.KnownHyperlinksDetector();
+ return result;
+ }
+ }
+
+ @Override
+ public String[] getConfiguredContentTypes(
+ ISourceViewer sourceViewer) {
+ return new String[] { IDocument.DEFAULT_CONTENT_TYPE,
+ CommitMessageViewer.HEADER_CONTENT_TYPE,
+ CommitMessageViewer.FOOTER_CONTENT_TYPE };
+ }
+
+ @Override
+ public IPresentationReconciler getPresentationReconciler(
+ ISourceViewer viewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+ reconciler.setDocumentPartitioning(
+ getConfiguredDocumentPartitioning(viewer));
+ DefaultDamagerRepairer hyperlinkDamagerRepairer = new DefaultDamagerRepairer(
+ new HyperlinkTokenScanner(this, viewer));
+ reconciler.setDamager(hyperlinkDamagerRepairer,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(hyperlinkDamagerRepairer,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ TextAttribute headerDefault = new TextAttribute(
+ PlatformUI.getWorkbench().getDisplay()
+ .getSystemColor(SWT.COLOR_DARK_GRAY));
+ DefaultDamagerRepairer headerDamagerRepairer = new DefaultDamagerRepairer(
+ new HyperlinkTokenScanner(this, viewer, headerDefault));
+ reconciler.setDamager(headerDamagerRepairer,
+ CommitMessageViewer.HEADER_CONTENT_TYPE);
+ reconciler.setRepairer(headerDamagerRepairer,
+ CommitMessageViewer.HEADER_CONTENT_TYPE);
+ DefaultDamagerRepairer footerDamagerRepairer = new DefaultDamagerRepairer(
+ new FooterTokenScanner(this, viewer));
+ reconciler.setDamager(footerDamagerRepairer,
+ CommitMessageViewer.FOOTER_CONTENT_TYPE);
+ reconciler.setRepairer(footerDamagerRepairer,
+ CommitMessageViewer.FOOTER_CONTENT_TYPE);
+ return reconciler;
+ }
+
+ };
+
+ commentViewer.configure(configuration);
+
+ diffViewer = new DiffViewer(commentAndDiffComposite, null, SWT.NONE);
+ diffViewer.configure(
+ new DiffViewer.Configuration(EditorsUI.getPreferenceStore()));
+ diffViewer.getControl().setLayoutData(
+ GridDataFactory.fillDefaults().grab(true, false).create());
+ diffViewer.addTextInputListener(new ITextInputListener() {
+
+ @Override
+ public void inputDocumentChanged(IDocument oldInput,
+ IDocument newInput) {
+ diffCaret = new Point(0, 0);
+ }
+
+ @Override
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ // Nothing
+ }
+ });
+ diffViewer.addTextListener(
+ event -> resizeCommentAndDiffScrolledComposite());
+
+ ActionUtils.UpdateableAction selectAll = ActionUtils.createGlobalAction(
+ ActionFactory.SELECT_ALL,
+ () -> diffViewer.doOperation(ITextOperationTarget.SELECT_ALL),
+ () -> diffViewer
+ .canDoOperation(ITextOperationTarget.SELECT_ALL));
+ ActionUtils.UpdateableAction copy = ActionUtils.createGlobalAction(
+ ActionFactory.COPY,
+ () -> diffViewer.doOperation(ITextOperationTarget.COPY),
+ () -> diffViewer.canDoOperation(ITextOperationTarget.COPY));
+ ActionUtils.setGlobalActions(diffViewer.getControl(), copy, selectAll);
+ ShowWhitespaceAction showWhitespaceAction = new ShowWhitespaceAction(
+ diffViewer);
+ diffViewer.addSelectionChangedListener(e -> copy.update());
+ MenuManager contextMenu = new MenuManager();
+ contextMenu.setRemoveAllWhenShown(true);
+ contextMenu.addMenuListener(manager -> {
+ if (diffViewer.getDocument().getLength() > 0) {
+ manager.add(copy);
+ manager.add(selectAll);
+ manager.add(new Separator());
+ manager.add(showWhitespaceAction);
+ }
+ });
+ StyledText diffWidget = diffViewer.getTextWidget();
+ diffWidget.setMenu(contextMenu.createContextMenu(diffWidget));
+ diffWidget.addDisposeListener(e -> showWhitespaceAction.dispose());
+ diffWidget.addVerifyKeyListener(event -> {
+ // Get the current caret position *before* it moves (if it does)
+ int offset = diffWidget.getCaretOffset();
+ diffCaret = new Point(diffWidget.getLineAtOffset(offset), offset);
+ });
+ diffWidget.addCaretListener(event -> {
+ Point location = diffWidget.getLocationAtOffset(event.caretOffset);
+ location.y += diffViewer.getControl().getLocation().y;
+ scrollCommentAndDiff(location,
+ diffWidget.getLineHeight(event.caretOffset));
+ });
+
+ commentAndDiffScrolledComposite
+ .addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ if (!resizing && commentViewer.getTextWidget()
+ .getWordWrap()) {
+ resizeCommentAndDiffScrolledComposite();
+ }
+ }
+ });
+
+ // Continuous cursor navigation over the two viewers with the arrow keys
+ commentWidget.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (diffWidget.getCharCount() == 0) {
+ return;
+ }
+ if (e.keyCode == SWT.ARROW_DOWN) {
+ int lastLine = commentWidget.getLineCount() - 1;
+ if (commentCaret.x == lastLine
+ && commentWidget.getLineAtOffset(commentWidget
+ .getCaretOffset()) == lastLine) {
+ diffWidget.setFocus();
+ diffWidget.setCaretOffset(0);
+ }
+ } else if (e.keyCode == SWT.ARROW_RIGHT) {
+ int chars = commentWidget.getCharCount();
+ if (commentCaret.y == chars
+ && commentWidget.getCaretOffset() == chars) {
+ diffWidget.setFocus();
+ diffWidget.setCaretOffset(0);
+ }
+ }
+ }
+ });
+ diffWidget.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.ARROW_UP) {
+ if (diffCaret.x == 0 && diffWidget.getLineAtOffset(
+ diffWidget.getCaretOffset()) == 0) {
+ commentWidget.setFocus();
+ commentWidget
+ .setCaretOffset(commentWidget.getOffsetAtLine(
+ commentWidget.getLineCount() - 1));
+ }
+ } else if (e.keyCode == SWT.ARROW_LEFT) {
+ if (diffCaret.y == 0
+ && diffWidget.getCaretOffset() == 0) {
+ commentWidget.setFocus();
+ commentWidget
+ .setCaretOffset(commentWidget.getCharCount());
+ }
+ }
+ }
+ });
+
+ }
+
+ /**
+ * Retrieves the outermost control (a {@link Composite}) wrapping the
+ * viewers.
+ *
+ * @return the outermost control
+ */
+ public Control getControl() {
+ return commentAndDiffScrolledComposite;
+ }
+
+ /**
+ * Retrieves the {@link DiffViewer}.
+ *
+ * @return the {@link DiffViewer}
+ */
+ public DiffViewer getDiffViewer() {
+ return diffViewer;
+ }
+
+ /**
+ * Retrieves the {@link CommitMessageViewer}.
+ *
+ * @return the {@link CommitMessageViewer}
+ */
+ public CommitMessageViewer getCommitViewer() {
+ return commentViewer;
+ }
+
+ /**
+ * Sets word-wrapping on the text viewers.
+ *
+ * @param wrap
+ * whether to word-wrap
+ */
+ public void setWrap(boolean wrap) {
+ commentViewer.getTextWidget().setWordWrap(wrap);
+ diffViewer.getTextWidget().setWordWrap(wrap);
+ resizeCommentAndDiffScrolledComposite();
+ }
+
+ private void resizeCommentAndDiffScrolledComposite() {
+ resizing = true;
+ long start = 0;
+ int lines = 0;
+ boolean trace = GitTraceLocation.HISTORYVIEW.isActive();
+ if (trace) {
+ IDocument document = diffViewer.getDocument();
+ lines = document != null ? document.getNumberOfLines() : 0;
+ System.out.println("Lines: " + lines); //$NON-NLS-1$
+ if (lines > 1) {
+ new Exception("resizeCommentAndDiffScrolledComposite") //$NON-NLS-1$
+ .printStackTrace(System.out);
+ }
+ start = System.currentTimeMillis();
+ }
+
+ Point size = commentAndDiffComposite.computeSize(SWT.DEFAULT,
+ SWT.DEFAULT);
+ commentAndDiffComposite.layout();
+ commentAndDiffScrolledComposite.setMinSize(size);
+ resizing = false;
+
+ if (trace) {
+ long stop = System.currentTimeMillis();
+ long time = stop - start;
+ long lps = (lines * 1000) / (time + 1);
+ System.out
+ .println("Resize + diff: " + time + " ms, line/s: " + lps); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ private void scrollCommentAndDiff(Point location, int lineHeight) {
+ Rectangle size = commentAndDiffScrolledComposite.getBounds();
+ ScrollBar bar = commentAndDiffScrolledComposite.getVerticalBar();
+ if (bar != null && bar.isVisible()) {
+ size.width = Math.max(0, size.width - bar.getSize().x);
+ }
+ bar = commentAndDiffScrolledComposite.getHorizontalBar();
+ if (bar != null && bar.isVisible()) {
+ size.height = Math.max(0, size.height - bar.getSize().y);
+ }
+ Point topLeft = commentAndDiffScrolledComposite.getOrigin();
+ size.x = topLeft.x;
+ size.y = topLeft.y;
+ if (location.y >= size.y) {
+ location.y += lineHeight;
+ }
+ if (!size.contains(location)) {
+ int left = size.x;
+ int top = size.y;
+ // Use the same scrolling as in StyledText: scroll horizontally at
+ // least by width / 4. Otherwise horizontal scrolling is slow.
+ int minScroll = size.width / 4;
+ if (location.x < left) {
+ left = Math.max(0,
+ left - Math.max(left - location.x, minScroll));
+ } else if (location.x > left + size.width) {
+ int maxWidth = commentAndDiffComposite.getSize().x;
+ int right = Math.max(location.x, left + size.width + minScroll);
+ left = Math.min(right, maxWidth) - size.width;
+ }
+ if (location.y < top) {
+ top = location.y;
+ } else if (location.y > top + size.height) {
+ top = location.y - size.height;
+ }
+ commentAndDiffScrolledComposite.setOrigin(left, top);
+ }
+ }
+
+ private static class FooterTokenScanner extends HyperlinkTokenScanner {
+
+ private static final Pattern ITALIC_LINE = Pattern
+ .compile("^[A-Z](?:[A-Za-z]+-)+by: "); //$NON-NLS-1$
+
+ private final IToken italicToken;
+
+ public FooterTokenScanner(SourceViewerConfiguration configuration,
+ ISourceViewer viewer) {
+ super(configuration, viewer);
+ Object defaults = defaultToken.getData();
+ TextAttribute italic;
+ if (defaults instanceof TextAttribute) {
+ TextAttribute defaultAttribute = (TextAttribute) defaults;
+ int style = defaultAttribute.getStyle() ^ SWT.ITALIC;
+ italic = new TextAttribute(defaultAttribute.getForeground(),
+ defaultAttribute.getBackground(), style,
+ defaultAttribute.getFont());
+ } else {
+ italic = new TextAttribute(null, null, SWT.ITALIC);
+ }
+ italicToken = new Token(italic);
+ }
+
+ @Override
+ protected IToken scanToken() {
+ // If we're at a "Signed-off-by" or similar footer line, make it
+ // italic.
+ try {
+ IRegion region = document
+ .getLineInformationOfOffset(currentOffset);
+ if (currentOffset == region.getOffset()) {
+ String line = document.get(currentOffset,
+ region.getLength());
+ Matcher m = ITALIC_LINE.matcher(line);
+ if (m.find()) {
+ currentOffset = Math.min(endOfRange,
+ currentOffset + region.getLength());
+ return italicToken;
+ }
+ }
+ } catch (BadLocationException e) {
+ // Ignore and return null below.
+ }
+ return null;
+ }
+ }
+}
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 d6be435af..9ce8aa9e5 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
@@ -189,6 +189,7 @@ public class CommitFileDiffViewer extends TableViewer {
public CommitFileDiffViewer(final Composite parent,
final IWorkbenchSite site, final int style) {
super(parent, preventBug499850(style));
+ setUseHashlookup(true);
this.site = site;
final Table rawTable = getTable();
@@ -721,6 +722,7 @@ public class CommitFileDiffViewer extends TableViewer {
loader.cancel();
loader = null;
}
+ Job.getJobManager().cancel(JobFamilies.HISTORY_FILE_DIFF);
}
private static class FileDiffLoader extends Job {
@@ -795,7 +797,8 @@ public class CommitFileDiffViewer extends TableViewer {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
Control control = getControl();
- if (control == null || control.isDisposed() || loader != loadJob) {
+ if (control == null || control.isDisposed() || loader != loadJob
+ || monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
FileDiff[] diffs = loadJob.getDiffs();
@@ -828,6 +831,11 @@ public class CommitFileDiffViewer extends TableViewer {
return null;
}
+ @Override
+ public boolean belongsTo(Object family) {
+ return family == JobFamilies.HISTORY_FILE_DIFF
+ || super.belongsTo(family);
+ }
}
/**
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 3bbd68d54..0f96fe36d 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
@@ -418,7 +418,7 @@ public class FileDiff {
objectIds.add(diffEntry.getOldId().toObjectId());
if (diffEntry.getNewId() != null)
objectIds.add(diffEntry.getNewId().toObjectId());
- return objectIds.toArray(new ObjectId[]{});
+ return objectIds.toArray(new ObjectId[0]);
}
/**
@@ -432,7 +432,7 @@ public class FileDiff {
modes.add(diffEntry.getOldMode());
if (diffEntry.getOldMode() != null)
modes.add(diffEntry.getOldMode());
- return modes.toArray(new FileMode[]{});
+ return modes.toArray(new FileMode[0]);
}
/**
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java
index 3b49dfc18..518ccd365 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java
@@ -225,7 +225,7 @@ public class FindResults {
private Integer[] getkeysArray() {
if (keysArray == null) {
keysArray = matchesMap.keySet().toArray(
- new Integer[matchesMap.size()]);
+ new Integer[0]);
}
return keysArray;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarJob.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarJob.java
index f748f2e92..11f07e6fe 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarJob.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarJob.java
@@ -125,7 +125,8 @@ public class FindToolbarJob extends Job {
continue;
}
- if (findInCommitId && find(findPattern, revision.getId().name())) {
+ if (findInCommitId
+ && find(findPattern.trim(), revision.getId().name())) {
if (progress.isCanceled()) {
return Status.CANCEL_STATUS;
}
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 dd89b368f..3c206abd0 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
@@ -32,8 +32,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
@@ -56,7 +54,6 @@ import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.JobFamilies;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
-import org.eclipse.egit.ui.internal.ActionUtils;
import org.eclipse.egit.ui.internal.CompareUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
@@ -66,9 +63,6 @@ import org.eclipse.egit.ui.internal.commit.DiffViewer;
import org.eclipse.egit.ui.internal.commit.FocusTracker;
import org.eclipse.egit.ui.internal.components.DropDownMenuAction;
import org.eclipse.egit.ui.internal.components.RepositoryMenuUtil.RepositoryToolbarAction;
-import org.eclipse.egit.ui.internal.dialogs.HyperlinkSourceViewer;
-import org.eclipse.egit.ui.internal.dialogs.HyperlinkTokenScanner;
-import org.eclipse.egit.ui.internal.dialogs.ShowWhitespaceAction;
import org.eclipse.egit.ui.internal.fetch.FetchHeadChangedEvent;
import org.eclipse.egit.ui.internal.history.FindToolbar.StatusListener;
import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefNode;
@@ -86,14 +80,16 @@ import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.SubContributionItem;
+import org.eclipse.jface.action.SubToolBarManager;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.layout.GridDataFactory;
-import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
@@ -101,22 +97,8 @@ 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.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.ITextListener;
-import org.eclipse.jface.text.ITextOperationTarget;
-import org.eclipse.jface.text.TextAttribute;
-import org.eclipse.jface.text.TextEvent;
-import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
-import org.eclipse.jface.text.presentation.IPresentationReconciler;
-import org.eclipse.jface.text.presentation.PresentationReconciler;
-import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
-import org.eclipse.jface.text.rules.IToken;
-import org.eclipse.jface.text.rules.Token;
-import org.eclipse.jface.text.source.ISourceViewer;
-import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
@@ -154,11 +136,8 @@ import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
@@ -166,7 +145,6 @@ import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
@@ -185,7 +163,6 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.dialogs.PreferencesUtil;
-import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.ShowInContext;
@@ -691,8 +668,10 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
*
* @param newState
* the new state to apply.
+ * @param forceRefresh
+ * whether to force a refresh of the entire history page
*/
- private void applyNewState(boolean newState) {
+ private void applyNewState(boolean newState, boolean forceRefresh) {
Control control = historyPage.getControl();
if (control != null && !control.isDisposed()) {
control.getDisplay().asyncExec(() -> {
@@ -701,7 +680,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
}
});
}
- historyPage.refresh(historyPage.selectedCommit());
+ if (forceRefresh) {
+ historyPage.refresh(historyPage.selectedCommit());
+ }
}
@Override
@@ -714,7 +695,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
if (prefKey.equals(event.getProperty())) {
// global first parent preference changed and we have no
// current repo. Apply the new global preference
- applyNewState(historyPage.store.getBoolean(prefKey));
+ applyNewState(historyPage.store.getBoolean(prefKey),
+ true);
}
return;
}
@@ -725,13 +707,16 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
// global first parent preference changed, if this repo does
// not have a repo specific one apply the global one
if (!historyPage.store.contains(repoSpecificKey)) {
- applyNewState(historyPage.store.getBoolean(prefKey));
+ applyNewState(historyPage.store.getBoolean(prefKey),
+ true);
}
}
if (P_REPOSITORY.equals(event.getProperty())) {
// The repository was switched. Apply that correct state.
- applyNewState(historyPage.isShowFirstParentOnly());
+ // As the repository switch causes a refresh anyway don't do
+ // it again here.
+ applyNewState(historyPage.isShowFirstParentOnly(), false);
}
}
@@ -1002,16 +987,13 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
/** Split between {@link #graph} and {@link #revInfoSplit}. */
private SashForm graphDetailSplit;
- /** Split between {@link #commentViewer} and {@link #fileViewer}. */
+ /** Split between {@link #commitAndDiff} and {@link #fileViewer}. */
private SashForm revInfoSplit;
/** The table showing the DAG, first "paragraph", author, author date. */
private CommitGraphTable graph;
- /** Viewer displaying the currently selected commit of {@link #graph}. */
- private CommitMessageViewer commentViewer;
-
- private DiffViewer diffViewer;
+ private CommitAndDiffComponent commitAndDiff;
/** Viewer displaying file difference implied by {@link #graph}'s commit. */
private CommitFileDiffViewer fileViewer;
@@ -1068,7 +1050,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
|| UIPreferences.HISTORY_MAX_TAG_LENGTH.equals(prop))
graph.getTableView().refresh();
if (UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP.equals(prop)) {
- setWrap(((Boolean) event.getNewValue()).booleanValue());
+ commitAndDiff.setWrap(
+ ((Boolean) event.getNewValue()).booleanValue());
}
}
@@ -1128,12 +1111,6 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
private final RenameTracker renameTracker = new RenameTracker();
- private ScrolledComposite commentAndDiffScrolledComposite;
-
- private Composite commentAndDiffComposite;
-
- private volatile boolean resizing;
-
private final HistoryPageRule pageSchedulingRule;
/** Toolbar to find commits in the history view. */
@@ -1337,6 +1314,18 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
wasVisible = false;
}
+ private void workAroundBug551067(boolean visible) {
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=551067
+ IContributionManager parent = getParent();
+ if (parent instanceof SubToolBarManager) {
+ SubToolBarManager subManager = (SubToolBarManager) parent;
+ IContributionItem item = subManager.getParent().find(getId());
+ if (item instanceof SubContributionItem) {
+ item.setVisible(visible && subManager.isVisible());
+ }
+ }
+ }
+
@Override
public void setVisible(boolean visible) {
if (visible != isVisible()) {
@@ -1344,6 +1333,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
beforeHide();
}
super.setVisible(visible);
+ workAroundBug551067(visible);
// Update the toolbar. Will dispose our FindToolbar widget on
// hide, and will create a new one (through createControl())
// on show. It'll also reposition the toolbar, if needed.
@@ -1473,148 +1463,11 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
revInfoSplit = new SashForm(graphDetailSplit, SWT.HORIZONTAL);
- commentAndDiffScrolledComposite = new ScrolledComposite(revInfoSplit,
- SWT.H_SCROLL | SWT.V_SCROLL);
- commentAndDiffScrolledComposite.setExpandHorizontal(true);
- commentAndDiffScrolledComposite.setExpandVertical(true);
-
- commentAndDiffComposite = new Composite(commentAndDiffScrolledComposite, SWT.NONE);
- commentAndDiffScrolledComposite.setContent(commentAndDiffComposite);
- commentAndDiffComposite.setLayout(GridLayoutFactory.fillDefaults()
- .create());
-
- commentViewer = new CommitMessageViewer(commentAndDiffComposite,
- getPartSite());
- commentViewer.getControl().setLayoutData(
- GridDataFactory.fillDefaults().grab(true, false).create());
-
- commentViewer.addTextListener(new ITextListener() {
- @Override
- public void textChanged(TextEvent event) {
- resizeCommentAndDiffScrolledComposite();
- }
- });
-
- commentAndDiffComposite.setBackground(commentViewer.getControl()
- .getBackground());
-
-
- HyperlinkSourceViewer.Configuration configuration = new HyperlinkSourceViewer.Configuration(
- EditorsUI.getPreferenceStore()) {
-
- @Override
- public int getHyperlinkStateMask(ISourceViewer sourceViewer) {
- return SWT.NONE;
- }
-
- @Override
- protected IHyperlinkDetector[] internalGetHyperlinkDetectors(
- ISourceViewer sourceViewer) {
- IHyperlinkDetector[] registered = super.internalGetHyperlinkDetectors(
- sourceViewer);
- // Always add our special detector for commit hyperlinks; we
- // want those to show always.
- if (registered == null) {
- return new IHyperlinkDetector[] {
- new CommitMessageViewer.KnownHyperlinksDetector() };
- } else {
- IHyperlinkDetector[] result = new IHyperlinkDetector[registered.length
- + 1];
- System.arraycopy(registered, 0, result, 0,
- registered.length);
- result[registered.length] = new CommitMessageViewer.KnownHyperlinksDetector();
- return result;
- }
- }
-
- @Override
- public String[] getConfiguredContentTypes(
- ISourceViewer sourceViewer) {
- return new String[] { IDocument.DEFAULT_CONTENT_TYPE,
- CommitMessageViewer.HEADER_CONTENT_TYPE,
- CommitMessageViewer.FOOTER_CONTENT_TYPE };
- }
-
- @Override
- public IPresentationReconciler getPresentationReconciler(
- ISourceViewer viewer) {
- PresentationReconciler reconciler = new PresentationReconciler();
- reconciler.setDocumentPartitioning(
- getConfiguredDocumentPartitioning(viewer));
- DefaultDamagerRepairer hyperlinkDamagerRepairer = new DefaultDamagerRepairer(
- new HyperlinkTokenScanner(this, viewer));
- reconciler.setDamager(hyperlinkDamagerRepairer,
- IDocument.DEFAULT_CONTENT_TYPE);
- reconciler.setRepairer(hyperlinkDamagerRepairer,
- IDocument.DEFAULT_CONTENT_TYPE);
- TextAttribute headerDefault = new TextAttribute(
- PlatformUI.getWorkbench().getDisplay()
- .getSystemColor(SWT.COLOR_DARK_GRAY));
- DefaultDamagerRepairer headerDamagerRepairer = new DefaultDamagerRepairer(
- new HyperlinkTokenScanner(this, viewer, headerDefault));
- reconciler.setDamager(headerDamagerRepairer,
- CommitMessageViewer.HEADER_CONTENT_TYPE);
- reconciler.setRepairer(headerDamagerRepairer,
- CommitMessageViewer.HEADER_CONTENT_TYPE);
- DefaultDamagerRepairer footerDamagerRepairer = new DefaultDamagerRepairer(
- new FooterTokenScanner(this, viewer));
- reconciler.setDamager(footerDamagerRepairer,
- CommitMessageViewer.FOOTER_CONTENT_TYPE);
- reconciler.setRepairer(footerDamagerRepairer,
- CommitMessageViewer.FOOTER_CONTENT_TYPE);
- return reconciler;
- }
-
- };
+ commitAndDiff = new CommitAndDiffComponent(revInfoSplit, getPartSite());
- commentViewer.configure(configuration);
-
- diffViewer = new DiffViewer(commentAndDiffComposite, null, SWT.NONE);
- diffViewer.configure(
- new DiffViewer.Configuration(EditorsUI.getPreferenceStore()));
- diffViewer.getControl().setLayoutData(
- GridDataFactory.fillDefaults().grab(true, false).create());
-
- ActionUtils.UpdateableAction selectAll = ActionUtils.createGlobalAction(
- ActionFactory.SELECT_ALL,
- () -> diffViewer.doOperation(ITextOperationTarget.SELECT_ALL),
- () -> diffViewer
- .canDoOperation(ITextOperationTarget.SELECT_ALL));
- ActionUtils.UpdateableAction copy = ActionUtils.createGlobalAction(
- ActionFactory.COPY,
- () -> diffViewer.doOperation(ITextOperationTarget.COPY),
- () -> diffViewer.canDoOperation(ITextOperationTarget.COPY));
- ActionUtils.setGlobalActions(diffViewer.getControl(), copy, selectAll);
- ShowWhitespaceAction showWhitespaceAction = new ShowWhitespaceAction(
- diffViewer);
- diffViewer.addSelectionChangedListener(e -> copy.update());
- MenuManager contextMenu = new MenuManager();
- contextMenu.setRemoveAllWhenShown(true);
- contextMenu.addMenuListener(manager -> {
- if (diffViewer.getDocument().getLength() > 0) {
- manager.add(copy);
- manager.add(selectAll);
- manager.add(new Separator());
- manager.add(showWhitespaceAction);
- }
- });
- StyledText diffWidget = diffViewer.getTextWidget();
- diffWidget.setMenu(contextMenu.createContextMenu(diffWidget));
- diffWidget.addDisposeListener(e -> showWhitespaceAction.dispose());
-
- setWrap(store
+ commitAndDiff.setWrap(store
.getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP));
- commentAndDiffScrolledComposite.addControlListener(new ControlAdapter() {
- @Override
- public void controlResized(ControlEvent e) {
- if (!resizing && commentViewer.getTextWidget()
- .getWordWrap()) {
- resizeCommentAndDiffScrolledComposite();
- }
- }
- });
-
fileViewer = new CommitFileDiffViewer(revInfoSplit, getSite());
fileViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
@@ -1648,8 +1501,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
// last focused one in setFocus().
focusTracker = new FocusTracker();
trackFocus(graph.getTable());
- trackFocus(diffViewer.getControl());
- trackFocus(commentViewer.getControl());
+ trackFocus(commitAndDiff.getDiffViewer().getControl());
+ trackFocus(commitAndDiff.getCommitViewer().getControl());
trackFocus(fileViewer.getControl());
layout();
@@ -1727,7 +1580,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
revInfoSplit.setMaximizedControl(null);
} else if (showComment && !showFiles) {
graphDetailSplit.setMaximizedControl(null);
- revInfoSplit.setMaximizedControl(commentViewer.getControl());
+ revInfoSplit.setMaximizedControl(
+ commitAndDiff.getCommitViewer().getControl());
} else if (!showComment && showFiles) {
graphDetailSplit.setMaximizedControl(null);
revInfoSplit.setMaximizedControl(fileViewer.getControl());
@@ -1737,6 +1591,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
}
private void attachCommitSelectionChanged() {
+ CommitMessageViewer commentViewer = commitAndDiff.getCommitViewer();
graph.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(final SelectionChangedEvent event) {
@@ -1966,7 +1821,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
selectedObj = null;
name = ""; //$NON-NLS-1$
input = null;
- commentViewer.setInput(null);
+ commitAndDiff.getCommitViewer().setInput(null);
fileViewer.newInput(null);
setInput(null);
}
@@ -2927,11 +2782,11 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
private void formatDiffs(final List<FileDiff> diffs) {
Job.getJobManager().cancel(JobFamilies.HISTORY_DIFF);
+ DiffViewer diffViewer = commitAndDiff.getDiffViewer();
if (diffs.isEmpty()) {
if (UIUtils.isUsable(diffViewer)) {
IDocument document = new Document();
diffViewer.setDocument(document);
- resizeCommentAndDiffScrolledComposite();
}
return;
}
@@ -2977,7 +2832,6 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
}
if (UIUtils.isUsable(diffViewer)) {
diffViewer.setDocument(document);
- resizeCommentAndDiffScrolledComposite();
}
return Status.OK_STATUS;
}
@@ -3001,42 +2855,6 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
schedule(formatJob);
}
- private void setWrap(boolean wrap) {
- commentViewer.getTextWidget().setWordWrap(wrap);
- diffViewer.getTextWidget().setWordWrap(wrap);
- resizeCommentAndDiffScrolledComposite();
- }
-
- private void resizeCommentAndDiffScrolledComposite() {
- resizing = true;
- long start = 0;
- int lines = 0;
- if (trace) {
- IDocument document = diffViewer.getDocument();
- lines = document != null ? document.getNumberOfLines() : 0;
- System.out.println("Lines: " + lines); //$NON-NLS-1$
- if (lines > 1) {
- new Exception("resizeCommentAndDiffScrolledComposite") //$NON-NLS-1$
- .printStackTrace(System.out);
- }
- start = System.currentTimeMillis();
- }
-
- Point size = commentAndDiffComposite
- .computeSize(SWT.DEFAULT, SWT.DEFAULT);
- commentAndDiffComposite.layout();
- commentAndDiffScrolledComposite.setMinSize(size);
- resizing = false;
-
- if (trace) {
- long stop = System.currentTimeMillis();
- long time = stop - start;
- long lps = (lines * 1000) / (time + 1);
- System.out
- .println("Resize + diff: " + time + " ms, line/s: " + lps); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
private TreeWalk createFileWalker(RevWalk walk, Repository db, List<FilterPath> paths) {
final TreeWalk fileWalker = new TreeWalk(db);
fileWalker.setRecursive(true);
@@ -3236,52 +3054,4 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
public String getRenamedPath(String path, ObjectId commit) {
return renameTracker.getPath(commit, path);
}
-
- private static class FooterTokenScanner extends HyperlinkTokenScanner {
-
- private static final Pattern ITALIC_LINE = Pattern
- .compile("^[A-Z](?:[A-Za-z]+-)+by: "); //$NON-NLS-1$
-
- private final IToken italicToken;
-
- public FooterTokenScanner(SourceViewerConfiguration configuration,
- ISourceViewer viewer) {
- super(configuration, viewer);
- Object defaults = defaultToken.getData();
- TextAttribute italic;
- if (defaults instanceof TextAttribute) {
- TextAttribute defaultAttribute = (TextAttribute) defaults;
- int style = defaultAttribute.getStyle() ^ SWT.ITALIC;
- italic = new TextAttribute(defaultAttribute.getForeground(),
- defaultAttribute.getBackground(), style,
- defaultAttribute.getFont());
- } else {
- italic = new TextAttribute(null, null, SWT.ITALIC);
- }
- italicToken = new Token(italic);
- }
-
- @Override
- protected IToken scanToken() {
- // If we're at a "Signed-off-by" or similar footer line, make it
- // italic.
- try {
- IRegion region = document
- .getLineInformationOfOffset(currentOffset);
- if (currentOffset == region.getOffset()) {
- String line = document.get(currentOffset,
- region.getLength());
- Matcher m = ITALIC_LINE.matcher(line);
- if (m.find()) {
- currentOffset = Math.min(endOfRange,
- currentOffset + region.getLength());
- return italicToken;
- }
- }
- } catch (BadLocationException e) {
- // Ignore and return null below.
- }
- return null;
- }
- }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java
index 3e6b63363..61d9c7704 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java
@@ -56,6 +56,8 @@ public class GitPreferenceRoot extends DoublePreferencesPreferencePage
private final static String[][] SSH_CLIENT_NAMES_AND_VALUES = new String[2][2];
+ private final static String[][] HTTP_CLIENT_NAMES_AND_VALUES = new String[2][2];
+
private final static boolean HAS_DEBUG_UI = hasDebugUiBundle();
static {
@@ -70,6 +72,11 @@ public class GitPreferenceRoot extends DoublePreferencesPreferencePage
SSH_CLIENT_NAMES_AND_VALUES[0][1] = "jsch"; //$NON-NLS-1$
SSH_CLIENT_NAMES_AND_VALUES[1][0] = UIText.GitPreferenceRoot_SshClient_Apache_Label;
SSH_CLIENT_NAMES_AND_VALUES[1][1] = "apache"; //$NON-NLS-1$
+
+ HTTP_CLIENT_NAMES_AND_VALUES[0][0] = UIText.GitPreferenceRoot_HttpClient_Jdk_Label;
+ HTTP_CLIENT_NAMES_AND_VALUES[0][1] = "jdk"; //$NON-NLS-1$
+ HTTP_CLIENT_NAMES_AND_VALUES[1][0] = UIText.GitPreferenceRoot_HttpClient_Apache_Label;
+ HTTP_CLIENT_NAMES_AND_VALUES[1][1] = "apache"; //$NON-NLS-1$
}
/**
@@ -225,6 +232,18 @@ public class GitPreferenceRoot extends DoublePreferencesPreferencePage
};
addField(sshClient);
+ ComboFieldEditor httpClient = new ComboFieldEditor(
+ GitCorePreferences.core_httpClient,
+ UIText.RemoteConnectionPreferencePage_HttpClientLabel,
+ HTTP_CLIENT_NAMES_AND_VALUES, remoteConnectionsGroup) {
+
+ @Override
+ public IPreferenceStore getPreferenceStore() {
+ return getSecondaryPreferenceStore();
+ }
+
+ };
+ addField(httpClient);
updateMargins(remoteConnectionsGroup);
Group repoChangeScannerGroup = new Group(main, SWT.SHADOW_ETCHED_IN);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/SynchronizePreferencePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/SynchronizePreferencePage.java
index e0e3a7ab6..3816d7b20 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/SynchronizePreferencePage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/SynchronizePreferencePage.java
@@ -114,7 +114,7 @@ public class SynchronizePreferencePage extends FieldEditorPreferencePage
strategies.add(new String[] { strategy.getLabel(),
strategy.getName() });
}
- return strategies.toArray(new String[strategies.size()][2]);
+ return strategies.toArray(new String[0][0]);
}
private ScopedPreferenceStore getCorePreferenceStore() {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
index 6bd1de6cf..506bfc406 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
@@ -80,8 +80,7 @@ public class PullOperationUI extends JobChangeAdapter {
* @param repositories
*/
public PullOperationUI(Set<Repository> repositories) {
- this.repositories = repositories.toArray(new Repository[repositories
- .size()]);
+ this.repositories = repositories.toArray(new Repository[0]);
int timeout = Activator.getDefault().getPreferenceStore().getInt(
UIPreferences.REMOTE_CONNECTION_TIMEOUT);
pullOperation = new PullOperation(repositories, timeout);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java
index 555899bfb..94726e8dd 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java
@@ -569,8 +569,7 @@ public class RebaseResultDialog extends MessageDialog {
IPath location = repoWorkdirPath.append(repoPath);
locationList.add(location);
}
- IPath[] locations = locationList.toArray(new IPath[locationList
- .size()]);
+ IPath[] locations = locationList.toArray(new IPath[0]);
int mergeMode = Activator.getDefault().getPreferenceStore()
.getInt(UIPreferences.MERGE_MODE);
CompareEditorInput input;
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 e1da30586..025d72b64 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
@@ -432,6 +432,10 @@ public class RepositoriesView extends CommonNavigator implements IShowInSource,
TreeSelection sel = (TreeSelection) event.getSelection();
RepositoryTreeNode element = (RepositoryTreeNode) sel
.getFirstElement();
+ // after deletion the selection can be empty
+ if (element == null) {
+ return;
+ }
// Disable checkout for bare repositories
if (element.getRepository().isBare()) {
return;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/EditableRevision.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/EditableRevision.java
index 07395793f..c31a8de48 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/EditableRevision.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/EditableRevision.java
@@ -96,81 +96,7 @@ public class EditableRevision extends FileRevisionTypedElement implements
public IEditorInput getDocumentKey(Object element) {
if (element == this) {
if (input == null) {
- input = new IStorageEditorInput() {
-
- @Override
- public boolean exists() {
- return true;
- }
-
- @Override
- public ImageDescriptor getImageDescriptor() {
- return null;
- }
-
- @Override
- public String getName() {
- return EditableRevision.this.getName();
- }
-
- @Override
- public IPersistableElement getPersistable() {
- return null;
- }
-
- @Override
- public String getToolTipText() {
- return EditableRevision.this.getName();
- }
-
- @Override
- public <T> T getAdapter(Class<T> adapter) {
- return null;
- }
-
- private IStorage storage;
-
- @Override
- public IStorage getStorage() throws CoreException {
- if (storage == null) {
- storage = new IEncodedStorage() {
-
- @Override
- public <T> T getAdapter(Class<T> adapter) {
- return null;
- }
-
- @Override
- public boolean isReadOnly() {
- return false;
- }
-
- @Override
- public String getName() {
- return EditableRevision.this.getName();
- }
-
- @Override
- public IPath getFullPath() {
- return null;
- }
-
- @Override
- public InputStream getContents()
- throws CoreException {
- return EditableRevision.this.getContents();
- }
-
- @Override
- public String getCharset()
- throws CoreException {
- return EditableRevision.this.getCharset();
- }
- };
- }
- return storage;
- }
- };
+ input = new FakeResourceStorageEditorInput(this);
}
return input;
}
@@ -193,6 +119,20 @@ public class EditableRevision extends FileRevisionTypedElement implements
}
/**
+ * Adapt the given editor input. May be overridden in subclasses.
+ *
+ * @param editorInput
+ * of this revision
+ * @param adapter
+ * to adapt to
+ * @return the adapted object or {@code null} if none
+ */
+ protected <T> T adaptEditorInput(IEditorInput editorInput,
+ Class<T> adapter) {
+ return null;
+ }
+
+ /**
* Notifies all registered <code>IContentChangeListener</code>s of a content
* change.
*/
@@ -297,9 +237,134 @@ public class EditableRevision extends FileRevisionTypedElement implements
}
@Override
+ public void connect(IDocumentProvider provider,
+ IEditorInput documentKey) throws CoreException {
+ if (documentKey instanceof FakeResourceStorageEditorInput) {
+ // When we connect, our editor input shouldn't adapt to
+ // that (non-existing) resource, otherwise we'll confuse
+ // other parts of Eclipse.
+ FakeResourceStorageEditorInput input = (FakeResourceStorageEditorInput) documentKey;
+ try {
+ input.setAdapt(false);
+ super.connect(provider, input);
+ } finally {
+ // Once we _are_ connected, there are other places
+ // where SharedDocumentAdapter.getDocumentProvider()
+ // is called again during the life of the document,
+ // so the documentKey must again adapt to IFile.
+ input.setAdapt(true);
+ }
+ } else {
+ super.connect(provider, documentKey);
+ }
+ }
+
+ @Override
public IEditorInput getDocumentKey(Object element) {
return editable.getDocumentKey(element);
}
}
+ /**
+ * @see org.eclipse.egit.ui.internal.synchronize.compare.LocalNonWorkspaceTypedElement
+ */
+ private static class FakeResourceStorageEditorInput
+ implements IStorageEditorInput {
+
+ // This class and the connect() override above are a work-around for bug
+ // 544315: the file extension is used to find the document provider only
+ // if the editor input adapts to IFile.
+
+ // TODO: figure out a way to use a FileStoreEditorInput instead
+ // (perhaps with a little EFS to access the index). Then this hack
+ // could be removed once EGit's base platform is Eclipse 4.11
+ // (2019-03).
+
+ private final EditableRevision editable;
+
+ private boolean adapt;
+
+ public FakeResourceStorageEditorInput(EditableRevision revision) {
+ editable = revision;
+ adapt = true;
+ }
+
+ public void setAdapt(boolean adapt) {
+ this.adapt = adapt;
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return editable.getName();
+ }
+
+ @Override
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ @Override
+ public String getToolTipText() {
+ return editable.getName();
+ }
+
+ @Override
+ public <T> T getAdapter(Class<T> adapter) {
+ if (adapt) {
+ return editable.adaptEditorInput(this, adapter);
+ }
+ return null;
+ }
+
+ private IStorage storage;
+
+ @Override
+ public IStorage getStorage() throws CoreException {
+ if (storage == null) {
+ storage = new IEncodedStorage() {
+
+ @Override
+ public <T> T getAdapter(Class<T> adapter) {
+ return null;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public String getName() {
+ return editable.getName();
+ }
+
+ @Override
+ public IPath getFullPath() {
+ return null;
+ }
+
+ @Override
+ public InputStream getContents() throws CoreException {
+ return editable.getContents();
+ }
+
+ @Override
+ public String getCharset() throws CoreException {
+ return editable.getCharset();
+ }
+ };
+ }
+ return storage;
+ }
+ }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/LocationEditableRevision.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/LocationEditableRevision.java
index 3c7dc2845..3018b0080 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/LocationEditableRevision.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/LocationEditableRevision.java
@@ -28,6 +28,7 @@ import org.eclipse.egit.ui.Activator;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.ui.IEditorInput;
/**
* Editable revision backed by a file outside of the workspace (just IPath).
@@ -88,6 +89,18 @@ public class LocationEditableRevision extends EditableRevision {
}
@Override
+ protected <T> T adaptEditorInput(IEditorInput editorInput,
+ Class<T> adapter) {
+ // Ugly hack to ensure the framework finds the correct document
+ // provider.
+ if (adapter == IFile.class) {
+ return adapter.cast(
+ ResourcesPlugin.getWorkspace().getRoot().getFile(location));
+ }
+ return super.adaptEditorInput(editorInput, adapter);
+ }
+
+ @Override
public int hashCode() {
return 31 * super.hashCode() + Objects.hash(location, runnableContext);
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/ResourceEditableRevision.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/ResourceEditableRevision.java
index b2be7fb49..4c332877e 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/ResourceEditableRevision.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/revision/ResourceEditableRevision.java
@@ -25,6 +25,7 @@ import org.eclipse.egit.ui.Activator;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.ui.IEditorInput;
/**
* Editable revision backed by an {@link IFile}. Used for conflict resolutions
@@ -96,6 +97,15 @@ public class ResourceEditableRevision extends EditableRevision
}
@Override
+ protected <T> T adaptEditorInput(IEditorInput editorInput,
+ Class<T> adapter) {
+ if (adapter == IResource.class || adapter == IFile.class) {
+ return adapter.cast(file);
+ }
+ return super.adaptEditorInput(editorInput, adapter);
+ }
+
+ @Override
public int hashCode() {
return 31 * super.hashCode() + Objects.hash(file, runnableContext);
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java
index 3fcbbe17d..e2f79026d 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java
@@ -207,8 +207,7 @@ public class SharingWizard extends Wizard implements IConfigurationWizard,
@Override
public void run() {
activePage.closeEditors(
- editorRefsToClose.toArray(
- new IEditorReference[editorRefsToClose.size()]),
+ editorRefsToClose.toArray(new IEditorReference[0]),
true);
}
});
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 31a7a2ba4..ff18bf07e 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
@@ -804,7 +804,7 @@ public class StagingView extends ViewPart
UIIcons.UNSTAGE) {
@Override
public void run() {
- unstage(stagedViewer.getStructuredSelection());
+ unstage(stagedViewer.getStructuredSelection().toList());
}
};
unstageAction.setToolTipText(UIText.StagingView_UnstageItemTooltip);
@@ -812,7 +812,7 @@ public class StagingView extends ViewPart
UIIcons.ELCL16_ADD) {
@Override
public void run() {
- stage(unstagedViewer.getStructuredSelection());
+ stage(unstagedViewer.getStructuredSelection().toList());
}
};
stageAction.setToolTipText(UIText.StagingView_StageItemTooltip);
@@ -825,8 +825,8 @@ public class StagingView extends ViewPart
UIIcons.UNSTAGE_ALL) {
@Override
public void run() {
- stagedViewer.getTree().selectAll();
- unstage(stagedViewer.getStructuredSelection());
+ unstage(Arrays.asList(
+ getContentProvider(stagedViewer).getStagingEntries()));
}
};
unstageAllAction
@@ -835,8 +835,8 @@ public class StagingView extends ViewPart
UIIcons.ELCL16_ADD_ALL) {
@Override
public void run() {
- unstagedViewer.getTree().selectAll();
- stage(unstagedViewer.getStructuredSelection());
+ stage(Arrays.asList(getContentProvider(unstagedViewer)
+ .getStagingEntries()));
}
};
stageAllAction.setToolTipText(UIText.StagingView_StageAllItemTooltip);
@@ -861,7 +861,7 @@ public class StagingView extends ViewPart
GridLayoutFactory.fillDefaults().applyTo(unstagedComposite);
unstagedViewer = createViewer(unstagedComposite, true,
- selection -> unstage(selection), stageAction);
+ selection -> unstage(selection.toList()), stageAction);
unstagedViewer.addSelectionChangedListener(event -> {
boolean hasSelection = !event.getSelection().isEmpty();
@@ -1145,7 +1145,7 @@ public class StagingView extends ViewPart
GridLayoutFactory.fillDefaults().applyTo(stagedComposite);
stagedViewer = createViewer(stagedComposite, false,
- selection -> stage(selection), unstageAction);
+ selection -> stage(selection.toList()), unstageAction);
stagedViewer.getLabelProvider().addListener(event -> {
updateMessage();
updateCommitButtons();
@@ -2842,7 +2842,7 @@ public class StagingView extends ViewPart
UIIcons.ELCL16_ADD) {
@Override
public void run() {
- stage(selection);
+ stage(selection.toList());
}
});
}
@@ -2852,7 +2852,7 @@ public class StagingView extends ViewPart
UIIcons.UNSTAGE) {
@Override
public void run() {
- unstage(selection);
+ unstage(selection.toList());
}
});
}
@@ -3353,10 +3353,10 @@ public class StagingView extends ViewPart
schedule(job, false);
}
- private void stage(IStructuredSelection selection) {
+ private void stage(Collection<?> selectedEntries) {
StagingViewContentProvider contentProvider = getContentProvider(unstagedViewer);
final Repository repository = currentRepository;
- Iterator iterator = selection.iterator();
+ Iterator iterator = selectedEntries.iterator();
final Set<String> addPaths = new HashSet<>();
final Set<String> rmPaths = new HashSet<>();
resetPathsToExpand();
@@ -3485,11 +3485,11 @@ public class StagingView extends ViewPart
}
}
- private void unstage(IStructuredSelection selection) {
- if (selection.isEmpty())
+ private void unstage(Collection<?> selectedEntries) {
+ if (selectedEntries.isEmpty())
return;
- Collection<String> paths = processUnstageSelection(selection);
+ Collection<String> paths = processUnstageSelection(selectedEntries);
if (paths.isEmpty())
return;
@@ -3518,10 +3518,10 @@ public class StagingView extends ViewPart
}
private Collection<String> processUnstageSelection(
- IStructuredSelection selection) {
+ Collection<?> selectedEntries) {
Set<String> paths = new HashSet<>();
resetPathsToExpand();
- for (Object element : selection.toList()) {
+ for (Object element : selectedEntries) {
if (element instanceof StagingEntry) {
StagingEntry entry = (StagingEntry) element;
addUnstagePath(entry, paths);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java
index 856b1a6a7..d386626de 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java
@@ -83,8 +83,7 @@ public class GitSynchronizeWizard extends Wizard {
Set<IProject> selectedProjects
= page.getSelectedProjects();
GitModelSynchronize.launch(gsdSet, selectedProjects
- .toArray(new IResource[selectedProjects
- .size()]));
+ .toArray(new IResource[0]));
return true;
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
index 756641917..a5352019d 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
@@ -496,6 +496,8 @@ public class LocalNonWorkspaceTypedElement extends LocalResourceTypedElement {
// 544315: the file extension is used to find the document provider only
// if the editor input adapts to IFile.
+ // TODO: Remove when EGit's base platform is Eclipse 4.11 (2019-03)
+
private IResource resource;
public FakeResourceFileStoreEditorInput(IFileStore store, IResource resource) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java
index 1f27a5b05..801aa1052 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java
@@ -90,7 +90,7 @@ public class GitModelRepository extends GitModelObjectContainer implements HasPr
@Override
public IProject[] getProjects() {
- return gsd.getProjects().toArray(new IProject[gsd.getProjects().size()]);
+ return gsd.getProjects().toArray(new IProject[0]);
}
@Override
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 dbc7ada86..77343184a 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
@@ -250,6 +250,8 @@ GitPreferenceRoot_CloningRepoGroupHeader=Cloning repositories
GitPreferenceRoot_DefaultRepoFolderLabel=Default repository &folder:
GitPreferenceRoot_DefaultRepoFolderTooltip=This folder will be suggested as parent folder when cloning a remote repository
GitPreferenceRoot_DefaultRepoFolderVariableButton=&Variable...
+GitPreferenceRoot_HttpClient_Jdk_Label=Java built-in HTTP
+GitPreferenceRoot_HttpClient_Apache_Label=Apache HTTP
GitPreferenceRoot_MergeGroupHeader=Merge
GitPreferenceRoot_MergeMode_0_Label=Prompt when starting tool
GitPreferenceRoot_MergeMode_1_Label=Workspace (pre-merged by Git)
@@ -1437,7 +1439,7 @@ GitSelectRepositoryPage_AddButton=&Add...
GitSelectRepositoryPage_AddTooltip=Add a Git repository from the local file system
GitSelectRepositoryPage_NoRepoFoundMessage=No repositories found, please clone or add a repository
GitSelectRepositoryPage_NoRepository=No repositories found
-GitSelectRepositoryPage_PageMessage=You can also clone a repository or add local repositories to the list
+GitSelectRepositoryPage_PageMessage=You can also add other local repositories to the list
GitSelectRepositoryPage_BareRepositoriesHidden=Bare repositories are not shown.
GitSelectRepositoryPage_PageTitle=Select a Git Repository
GitSelectRepositoryPage_PleaseSelectMessage=Please select a repository from the list
@@ -1765,6 +1767,7 @@ NotesEditorPage_Title=Notes
GitPreferenceRoot_MaxPullThreadsCount=&Maximum number of parallel pulls:
GitPreferenceRoot_MaxPullThreadsCountTooltip=1 disables parallel pulls
+RemoteConnectionPreferencePage_HttpClientLabel=&HTTP client:
RemoteConnectionPreferencePage_SshClientLabel=&SSH client:
RemoteConnectionPreferencePage_TimeoutLabel=&Connection timeout (seconds):
RemoteConnectionPreferencePage_ZeroValueTooltip=0 is equivalent to no timeout

Back to the top