diff options
author | Thomas Wolf | 2022-02-22 22:15:59 +0000 |
---|---|---|
committer | Thomas Wolf | 2022-02-22 22:25:38 +0000 |
commit | 4841b9f04419be9c5dfaf50ff89c5d8287bdac2d (patch) | |
tree | 01d32ef916958ca10637fd8d050fc76f8bf117d5 | |
parent | 42b7f0ef61c4726e37dcb6642952382af02616b9 (diff) | |
download | egit-4841b9f04419be9c5dfaf50ff89c5d8287bdac2d.tar.gz egit-4841b9f04419be9c5dfaf50ff89c5d8287bdac2d.tar.xz egit-4841b9f04419be9c5dfaf50ff89c5d8287bdac2d.zip |
[history] Fix UI freezes and word-wrap in commit & diff viewer
Recomputing the size of the combined commit & diff container could
cause extensive UI freezes and other UI lagginess if the diff was long
because of several reasons:
1. The size was recomputed far too often. It was done every time the
text presentation in either the commit or the diff viewer was
invalidated. But even hovering over a hyperlink invalidates part
of the text presentation.
2. There are two methods of computing the content size of a scrolled
composite, and EGit used the one that is apparently somewhat slower.
3. Word-wrapping was on by default in these viewers, even though they
didn't wrap because of a bug in the size calculation. Computing the
rendered size of a text with word-wrapping is slower than without.
Fix this by only recomputing the size when the input changes, using the
apparently somewhat faster method of updating the scrolled composite,
and switching off word-wrapping by default. When word-wrapping is on,
set a fixed width and compute only the height; this makes word-wrapping
work.
Additionally resizing the viewer by dragging the containing sash was
super slow if the diff was large because EGit recomputed the size on
every ResizeEvent. SWT emits ResizeEvents continuously while the
control is being resized.
Switch off live re-flowing the text (through continuously recomputing
the size) while the user resizes the control. Only do this once after
the user has stopped resizing the control. Resizing the control with
word-wrap on may still occasionally lag, but much less than before.
With word-wrap off, there is no need to recompute sizes at all, so in
this case resizing is now perfectly smooth.
Bug: 430226
Change-Id: If6a598e0ecea437ee2c0b139371ccc148a1cb57d
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r-- | org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java | 3 | ||||
-rw-r--r-- | org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitAndDiffComponent.java | 104 |
2 files changed, 87 insertions, 20 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java index c6577f154a..19b62915ff 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java @@ -55,7 +55,8 @@ public class PluginPreferenceInitializer extends AbstractPreferenceInitializer { store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_RELATIVE_DATE, true); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_EMAIL_ADDRESSES, false); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_NOTES, false); - store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP, true); + store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP, + false); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_DETAIL, true); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_COMMENT, true); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_TOOLTIPS, false); 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 index abef4748a8..e6c9f12dfb 100644 --- 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 @@ -50,6 +50,7 @@ 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.Display; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PlatformUI; @@ -80,9 +81,6 @@ public class CommitAndDiffComponent { private Point diffCaret = new Point(0, 0); - /** True during {@link #resizeCommentAndDiffScrolledComposite()}. */ - private volatile boolean resizing; - /** * Creates a new {@link CommitAndDiffComponent}. * @@ -94,8 +92,6 @@ public class CommitAndDiffComponent { 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); @@ -113,6 +109,7 @@ public class CommitAndDiffComponent { public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { commentCaret = new Point(0, 0); + resizeCommentAndDiffScrolledComposite(); } @Override @@ -121,8 +118,6 @@ public class CommitAndDiffComponent { // Nothing } }); - commentViewer.addTextListener( - event -> resizeCommentAndDiffScrolledComposite()); StyledText commentWidget = commentViewer.getTextWidget(); commentWidget.addVerifyKeyListener(event -> { @@ -140,6 +135,8 @@ public class CommitAndDiffComponent { commentAndDiffComposite .setBackground(commentViewer.getControl().getBackground()); + commentAndDiffScrolledComposite + .setBackground(commentViewer.getControl().getBackground()); HyperlinkSourceViewer.Configuration configuration = new HyperlinkSourceViewer.Configuration( EditorsUI.getPreferenceStore()) { @@ -222,6 +219,7 @@ public class CommitAndDiffComponent { public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { diffCaret = new Point(0, 0); + resizeCommentAndDiffScrolledComposite(); } @Override @@ -230,8 +228,6 @@ public class CommitAndDiffComponent { // Nothing } }); - diffViewer.addTextListener( - event -> resizeCommentAndDiffScrolledComposite()); ActionUtils.UpdateableAction selectAll = ActionUtils.createGlobalAction( ActionFactory.SELECT_ALL, @@ -271,13 +267,16 @@ public class CommitAndDiffComponent { diffWidget.getLineHeight(event.caretOffset)); }); - commentAndDiffScrolledComposite - .addControlListener(new ControlAdapter() { + // "Live" resizing the contents of the ScrolledComposite takes too long. + // Resize once after the resize is done. Note that resizing is needed + // only if word-wrap is on. + commentAndDiffScrolledComposite.addControlListener( + new Resizer(commentAndDiffScrolledComposite) { + @Override public void controlResized(ControlEvent e) { - if (!resizing && commentViewer.getTextWidget() - .getWordWrap()) { - resizeCommentAndDiffScrolledComposite(); + if (commentViewer.getTextWidget().getWordWrap()) { + super.controlResized(e); } } }); @@ -370,13 +369,32 @@ public class CommitAndDiffComponent { * whether to word-wrap */ public void setWrap(boolean wrap) { + if (Display.getCurrent() == null) { + StyledText text = commentViewer.getTextWidget(); + if (!text.isDisposed()) { + text.getDisplay().asyncExec(() -> { + if (text.isDisposed()) { + return; + } + internalSetWrap(wrap); + }); + } + } else { + internalSetWrap(wrap); + } + } + + private void internalSetWrap(boolean wrap) { commentViewer.getTextWidget().setWordWrap(wrap); diffViewer.getTextWidget().setWordWrap(wrap); resizeCommentAndDiffScrolledComposite(); } + private void resizeCommentAndDiffScrolledComposite() { - resizing = true; + if (commentAndDiffComposite.isDisposed()) { + return; + } long start = 0; int lines = 0; boolean trace = GitTraceLocation.HISTORYVIEW.isActive(); @@ -391,11 +409,25 @@ public class CommitAndDiffComponent { start = System.currentTimeMillis(); } - Point size = commentAndDiffComposite.computeSize(SWT.DEFAULT, + Point oldSize = commentAndDiffComposite.getSize(); + Rectangle minSize = commentAndDiffScrolledComposite.getClientArea(); + Point size; + StyledText text = commentViewer.getTextWidget(); + if (text == null) { + size = new Point(0, 0); + } else if (text.getWordWrap()) { + size = commentAndDiffComposite.computeSize(minSize.width, + SWT.DEFAULT); + } else { + size = commentAndDiffComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT); - commentAndDiffComposite.layout(); - commentAndDiffScrolledComposite.setMinSize(size); - resizing = false; + } + size.x = Math.max(minSize.width, size.x); + size.y = Math.max(minSize.height, size.y); + if (!size.equals(oldSize)) { + commentAndDiffComposite.setSize(size); + commentAndDiffComposite.layout(); + } if (trace) { long stop = System.currentTimeMillis(); @@ -503,4 +535,38 @@ public class CommitAndDiffComponent { return italicToken; } } + + private class Resizer extends ControlAdapter implements Runnable { + + private final Control control; + + private long lastEventTime; + + Resizer(Control control) { + this.control = control; + } + + @Override + public void controlResized(ControlEvent e) { + lastEventTime = System.currentTimeMillis(); + schedule(); + } + + private void schedule() { + control.getDisplay().timerExec(300, this); + } + + @Override + public void run() { + if (control.isDisposed()) { + return; + } + long now = System.currentTimeMillis(); + if (now - lastEventTime > 300) { + resizeCommentAndDiffScrolledComposite(); + } else { + schedule(); + } + } + } } |