SideBySide2: Defer syntax highlighting on large files

If a file contains more than 500 lines on either side defer syntax
highlighting by 250 milliseconds. This gives the browser a chance
to get the file opened and visible on screen before the active mode
starts chugging through the text building up the DOM.

Users see the file appear, and then CM3 highlights the visible
region and colors fill in slightly later. This gives the UI a
slightly more responsive feeling while still offering users the
syntax highlighting they want visible.

Change-Id: I86307406b93690d864e9fa652b19157667a75a82
This commit is contained in:
Shawn Pearce
2013-12-05 12:45:32 -08:00
committed by Colby Ranger
parent b6bfd66887
commit d62a6a94a4
4 changed files with 74 additions and 20 deletions

View File

@@ -2311,11 +2311,13 @@ As response a link:#diff-info[DiffInfo] entity is returned that describes the di
{
"meta_a": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 372
},
"meta_b": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 578
},
"change_type": "MODIFIED",
"diff_header": [
@@ -2379,11 +2381,13 @@ If the `intraline` parameter is specified, intraline differences are included in
{
"meta_a": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 372
},
"meta_b": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 578
},
"change_type": "MODIFIED",
"diff_header": [
@@ -2431,11 +2435,13 @@ be generated.
{
"meta_a": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 578
},
"meta_b": {
"name": "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java",
"content_type": "text/x-java-source"
"content_type": "text/x-java-source",
"lines": 578
},
"change_type": "MODIFIED",
"content": [
@@ -3008,6 +3014,7 @@ The `DiffFileMetaInfo` entity contains meta information about a file diff.
|Field Name |Description
|`name` |The name of the file.
|`content_type`|The content type of the file.
|`lines` |The total number of lines in the file.
|==========================
[[diff-info]]

View File

@@ -99,6 +99,7 @@ public class DiffInfo extends JavaScriptObject {
public static class FileMeta extends JavaScriptObject {
public final native String name() /*-{ return this.name; }-*/;
public final native String content_type() /*-{ return this.content_type; }-*/;
public final native int lines() /*-{ return this.lines || 0 }-*/;
protected FileMeta() {
}

View File

@@ -49,6 +49,7 @@ import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
@@ -122,6 +123,7 @@ public class SideBySide2 extends Screen {
private JsArray<CommentInfo> draftsBase;
private JsArray<CommentInfo> draftsRevision;
private DiffInfo diff;
private boolean largeFile;
private LineMapper mapper;
private List<TextMarker> markers;
private List<Runnable> undoLineClass;
@@ -188,10 +190,16 @@ public class SideBySide2 extends Screen {
@Override
public void onSuccess(DiffInfo diffInfo) {
diff = diffInfo;
new ModeInjector()
.add(getContentType(diff.meta_a()))
.add(getContentType(diff.meta_b()))
.inject(modeInjectorCb);
if (prefs.syntaxHighlighting()) {
largeFile = isLargeFile(diffInfo);
if (largeFile) {
modeInjectorCb.onSuccess(null);
} else {
injectMode(diffInfo, modeInjectorCb);
}
} else {
modeInjectorCb.onSuccess(null);
}
}
}));
@@ -514,6 +522,18 @@ public class SideBySide2 extends Screen {
resizeCodeMirror();
}
});
if (largeFile && prefs.syntaxHighlighting()) {
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
@Override
public boolean execute() {
if (prefs.syntaxHighlighting() && isAttached()) {
setSyntaxHighlighting(prefs.syntaxHighlighting());
}
return false;
}
}, 250);
}
}
private CodeMirror createCodeMirror(
@@ -526,7 +546,7 @@ public class SideBySide2 extends Screen {
.set("cursorHeight", 0.85)
.set("lineNumbers", true)
.set("tabSize", prefs.tabSize())
.set("mode", getContentType(meta))
.set("mode", largeFile ? null : getContentType(meta))
.set("lineWrapping", false)
.set("styleSelectedText", true)
.set("showTrailingSpace", prefs.showWhitespaceErrors())
@@ -563,14 +583,26 @@ public class SideBySide2 extends Screen {
prefsAction.update();
}
void setSyntaxHighlighting(final boolean b) {
operation(new Runnable() {
@Override
public void run() {
cmA.setOption("mode", b ? getContentType(diff.meta_a()) : null);
cmB.setOption("mode", b ? getContentType(diff.meta_b()) : null);
}
});
void setSyntaxHighlighting(boolean b) {
if (b) {
injectMode(diff, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
if (prefs.syntaxHighlighting()) {
cmA.setOption("mode", getContentType(diff.meta_a()));
cmB.setOption("mode", getContentType(diff.meta_b()));
}
}
@Override
public void onFailure(Throwable caught) {
prefs.syntaxHighlighting(false);
}
});
} else {
cmA.setOption("mode", (String) null);
cmB.setOption("mode", (String) null);
}
}
void setContext(final int context) {
@@ -1537,6 +1569,13 @@ public class SideBySide2 extends Screen {
: null;
}
private void injectMode(DiffInfo diffInfo, AsyncCallback<Void> cb) {
new ModeInjector()
.add(getContentType(diffInfo.meta_a()))
.add(getContentType(diffInfo.meta_b()))
.inject(cb);
}
DiffPreferences getPrefs() {
return prefs;
}
@@ -1614,4 +1653,9 @@ public class SideBySide2 extends Screen {
}
});
}
private static boolean isLargeFile(DiffInfo diffInfo) {
return (diffInfo.meta_a() != null && diffInfo.meta_a().lines() > 500)
|| (diffInfo.meta_b() != null && diffInfo.meta_b().lines() > 500);
}
}

View File

@@ -132,12 +132,14 @@ public class GetDiff implements RestReadView<FileResource> {
result.metaA = new FileMeta();
result.metaA.name = Objects.firstNonNull(ps.getOldName(), ps.getNewName());
result.metaA.setContentType(ps.getFileModeA(), ps.getMimeTypeA());
result.metaA.lines = ps.getA().size();
}
if (ps.getDisplayMethodB() != DisplayMethod.NONE) {
result.metaB = new FileMeta();
result.metaB.name = ps.getNewName();
result.metaB.setContentType(ps.getFileModeB(), ps.getMimeTypeB());
result.metaB.lines = ps.getB().size();
}
if (intraline) {
@@ -179,7 +181,7 @@ public class GetDiff implements RestReadView<FileResource> {
static class FileMeta {
String name;
String contentType;
String url;
Integer lines;
void setContentType(FileMode fileMode, String mimeType) {
switch (fileMode) {