Refactor common SideBySide2 CSS for CodeMirror

Move common style support for UI features into a new Extras class
that is attached to CodeMirror. The Extras class is compiled
Java code to allow the GWT compiler to construct short names for
all data fields that are Gerrit-specific.

Change-Id: I907068f451e3c1b0b65c772155dfa27f52fd80c9
This commit is contained in:
Shawn Pearce
2015-01-05 15:47:15 -08:00
parent 03dcbae5a8
commit 8fd5d7e592
11 changed files with 290 additions and 175 deletions

View File

@@ -147,7 +147,7 @@ class ChunkManager {
void adjustPadding() { void adjustPadding() {
if (paddingDivs != null) { if (paddingDivs != null) {
double h = host.getLineHeightPx(); double h = cmB.extras().lineHeightPx();
for (Element div : paddingDivs) { for (Element div : paddingDivs) {
int lines = div.getPropertyInt(DATA_LINES); int lines = div.getPropertyInt(DATA_LINES);
div.getStyle().setHeight(lines * h, Unit.PX); div.getStyle().setHeight(lines * h, Unit.PX);
@@ -291,7 +291,9 @@ class ChunkManager {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
int line = cm.hasActiveLine() ? cm.getLineNumber(cm.activeLine()) : 0; int line = cm.extras().hasActiveLine()
? cm.getLineNumber(cm.extras().activeLine())
: 0;
int res = Collections.binarySearch( int res = Collections.binarySearch(
chunks, chunks,
new DiffChunkInfo(cm.side(), line, 0, false), new DiffChunkInfo(cm.side(), line, 0, false),

View File

@@ -91,8 +91,8 @@ class CommentManager {
// It is only necessary to search one side to find a comment // It is only necessary to search one side to find a comment
// on either side of the editor pair. // on either side of the editor pair.
SortedMap<Integer, CommentGroup> map = map(src.side()); SortedMap<Integer, CommentGroup> map = map(src.side());
int line = src.hasActiveLine() int line = src.extras().hasActiveLine()
? src.getLineNumber(src.activeLine()) + 1 ? src.getLineNumber(src.extras().activeLine()) + 1
: 0; : 0;
if (dir == Direction.NEXT) { if (dir == Direction.NEXT) {
map = map.tailMap(line + 1); map = map.tailMap(line + 1);
@@ -295,9 +295,9 @@ class CommentManager {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
if (cm.hasActiveLine()) { if (cm.extras().hasActiveLine()) {
CommentGroup w = map(cm.side()).get( CommentGroup w = map(cm.side()).get(
cm.getLineNumber(cm.activeLine()) + 1); cm.getLineNumber(cm.extras().activeLine()) + 1);
if (w != null) { if (w != null) {
w.openCloseLast(); w.openCloseLast();
} }
@@ -310,9 +310,9 @@ class CommentManager {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
if (cm.hasActiveLine()) { if (cm.extras().hasActiveLine()) {
CommentGroup w = map(cm.side()).get( CommentGroup w = map(cm.side()).get(
cm.getLineNumber(cm.activeLine()) + 1); cm.getLineNumber(cm.extras().activeLine()) + 1);
if (w != null) { if (w != null) {
w.openCloseAll(); w.openCloseAll();
} }
@@ -327,8 +327,8 @@ class CommentManager {
@Override @Override
public void run() { public void run() {
String token = host.getToken(); String token = host.getToken();
if (cm.hasActiveLine()) { if (cm.extras().hasActiveLine()) {
LineHandle handle = cm.activeLine(); LineHandle handle = cm.extras().activeLine();
int line = cm.getLineNumber(handle) + 1; int line = cm.getLineNumber(handle) + 1;
token += "@" + (cm.side() == DisplaySide.A ? "a" : "") + line; token += "@" + (cm.side() == DisplaySide.A ? "a" : "") + line;
} }
@@ -340,7 +340,7 @@ class CommentManager {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
if (cm.hasActiveLine()) { if (cm.extras().hasActiveLine()) {
newDraft(cm); newDraft(cm);
} }
} }
@@ -348,7 +348,7 @@ class CommentManager {
} }
private void newDraft(CodeMirror cm) { private void newDraft(CodeMirror cm) {
int line = cm.getLineNumber(cm.activeLine()) + 1; int line = cm.getLineNumber(cm.extras().activeLine()) + 1;
if (cm.somethingSelected()) { if (cm.somethingSelected()) {
FromTo fromTo = cm.getSelectedRange(); FromTo fromTo = cm.getSelectedRange();
Pos end = fromTo.to(); Pos end = fromTo.to();

View File

@@ -48,14 +48,11 @@ class DiffTable extends Composite {
String dark(); String dark();
String diff(); String diff();
String noIntraline(); String noIntraline();
String activeLine();
String range(); String range();
String rangeHighlight(); String rangeHighlight();
String showTabs();
String showLineNumbers(); String showLineNumbers();
String hideA(); String hideA();
String hideB(); String hideB();
String columnMargin();
String padding(); String padding();
} }

View File

@@ -18,12 +18,11 @@ limitations under the License.
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:d='urn:import:com.google.gerrit.client.diff'> xmlns:d='urn:import:com.google.gerrit.client.diff'>
<ui:style type='com.google.gerrit.client.diff.DiffTable.DiffTableStyle'> <ui:style type='com.google.gerrit.client.diff.DiffTable.DiffTableStyle'>
@external .CodeMirror, .CodeMirror-lines, .CodeMirror-selectedtext; @external .CodeMirror, .CodeMirror-selectedtext;
@external .CodeMirror-linenumber; @external .CodeMirror-linenumber;
@external .CodeMirror-overlayscroll-vertical, .CodeMirror-scroll; @external .CodeMirror-overlayscroll-vertical, .CodeMirror-scroll;
@external .CodeMirror-dialog-bottom; @external .CodeMirror-dialog-bottom;
@external .cm-animate-fat-cursor, .CodeMirror-cursor; @external .cm-animate-fat-cursor, .CodeMirror-cursor;
@external .cm-searching, .cm-trailingspace, .cm-tab;
.fullscreen { .fullscreen {
background-color: #f7f7f7; background-color: #f7f7f7;
@@ -39,13 +38,10 @@ limitations under the License.
-ms-user-select: none; -ms-user-select: none;
} }
.difftable .CodeMirror-lines { padding: 0; }
.difftable .CodeMirror pre { .difftable .CodeMirror pre {
padding: 0;
overflow: hidden; overflow: hidden;
border-right: 0; border-right: 0;
width: auto; width: auto;
line-height: normal;
} }
/* Preserve space for underscores. If this changes /* Preserve space for underscores. If this changes
@@ -106,23 +102,12 @@ limitations under the License.
overflow-x: auto; overflow-x: auto;
} }
.activeLine .CodeMirror-linenumber {
background-color: #bcf !important;
color: #000;
}
.range { .range {
background-color: #ffd500 !important; background-color: #ffd500 !important;
} }
.rangeHighlight { .rangeHighlight {
background-color: #ffff00 !important; background-color: #ffff00 !important;
} }
.cm-searching {
background-color: #ffa !important;
}
.cm-trailingspace {
background-color: red !important;
}
.difftable .CodeMirror-selectedtext { .difftable .CodeMirror-selectedtext {
background-color: inherit !important; background-color: inherit !important;
} }
@@ -154,24 +139,10 @@ limitations under the License.
bottom: auto; bottom: auto;
left: auto; left: auto;
} }
.showTabs .cm-tab:before {
position: absolute;
content: "\00bb";
color: #f00;
}
.showLineNumbers .padding { .showLineNumbers .padding {
margin-left: 21px; margin-left: 21px;
border-left: 2px solid #d64040; border-left: 2px solid #d64040;
} }
.columnMargin {
position: absolute;
top: 0;
bottom: 0;
width: 0;
border-right: 1px dashed #ffa500;
z-index: 2;
cursor: text;
}
.diff_header { .diff_header {
font-size: 12px; font-size: 12px;

View File

@@ -13,26 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
@external .CodeMirror;
@external .CodeMirror-overlayscroll-horizontal;
@external .CodeMirror-overlayscroll-vertical;
.CodeMirror-overlayscroll-horizontal div {
min-width: 25px;
}
.CodeMirror-overlayscroll-vertical div {
min-height: 25px;
}
.CodeMirror .CodeMirror-overlayscroll-vertical {
z-index: inherit;
}
.CodeMirror .CodeMirror-overlayscroll-horizontal div,
.CodeMirror .CodeMirror-overlayscroll-vertical div {
background-color: rgba(128, 128, 128, 0.50);
z-index: 8;
}
.comment, .draft, .insert, .delete, .edit { .comment, .draft, .insert, .delete, .edit {
min-height: 5px; min-height: 5px;
position: absolute; position: absolute;

View File

@@ -48,7 +48,6 @@ import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyCodes;
@@ -58,7 +57,6 @@ import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FlowPanel;
@@ -71,7 +69,6 @@ import com.google.gwtexpui.globalkey.client.ShowHelpCommand;
import net.codemirror.lib.CodeMirror; import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler; import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler;
import net.codemirror.lib.CodeMirror.GutterClickHandler; import net.codemirror.lib.CodeMirror.GutterClickHandler;
import net.codemirror.lib.CodeMirror.LineClassWhere;
import net.codemirror.lib.CodeMirror.LineHandle; import net.codemirror.lib.CodeMirror.LineHandle;
import net.codemirror.lib.Configuration; import net.codemirror.lib.Configuration;
import net.codemirror.lib.KeyMap; import net.codemirror.lib.KeyMap;
@@ -120,10 +117,6 @@ public class SideBySide2 extends Screen {
private CodeMirror cmA; private CodeMirror cmA;
private CodeMirror cmB; private CodeMirror cmB;
private Element columnMarginA;
private Element columnMarginB;
private double charWidthPx;
private double lineHeightPx;
private HandlerRegistration resizeHandler; private HandlerRegistration resizeHandler;
private ScrollSynchronizer scrollSynchronizer; private ScrollSynchronizer scrollSynchronizer;
@@ -548,24 +541,21 @@ public class SideBySide2 extends Screen {
private void display(final CommentsCollections comments) { private void display(final CommentsCollections comments) {
setThemeStyles(prefs.theme().isDark()); setThemeStyles(prefs.theme().isDark());
setShowTabs(prefs.showTabs());
setShowIntraline(prefs.intralineDifference()); setShowIntraline(prefs.intralineDifference());
if (prefs.showLineNumbers()) { if (prefs.showLineNumbers()) {
diffTable.addStyleName(DiffTable.style.showLineNumbers()); diffTable.addStyleName(DiffTable.style.showLineNumbers());
} }
cmA = newCM(diff.meta_a(), diff.text_a(), diffTable.cmA).side(DisplaySide.A); cmA = newCM(diff.meta_a(), diff.text_a(), diffTable.cmA);
cmB = newCM(diff.meta_b(), diff.text_b(), diffTable.cmB).side(DisplaySide.B); cmB = newCM(diff.meta_b(), diff.text_b(), diffTable.cmB);
cmA.extras().side(DisplaySide.A);
cmB.extras().side(DisplaySide.B);
setShowTabs(prefs.showTabs());
chunkManager = new ChunkManager(this, cmA, cmB, diffTable.scrollbar); chunkManager = new ChunkManager(this, cmA, cmB, diffTable.scrollbar);
skipManager = new SkipManager(this, commentManager); skipManager = new SkipManager(this, commentManager);
columnMarginA = DOM.createDiv();
columnMarginB = DOM.createDiv();
columnMarginA.setClassName(DiffTable.style.columnMargin());
columnMarginB.setClassName(DiffTable.style.columnMargin());
cmA.mover().appendChild(columnMarginA);
cmB.mover().appendChild(columnMarginB);
if (prefs.renderEntireFile() && !canEnableRenderEntireFile(prefs)) { if (prefs.renderEntireFile() && !canEnableRenderEntireFile(prefs)) {
// CodeMirror is too slow to layout an entire huge file. // CodeMirror is too slow to layout an entire huge file.
prefs.renderEntireFile(false); prefs.renderEntireFile(false);
@@ -678,61 +668,14 @@ public class SideBySide2 extends Screen {
} }
} }
void setShowTabs(boolean b) { void setShowTabs(boolean show) {
if (b) { cmA.extras().showTabs(show);
diffTable.addStyleName(DiffTable.style.showTabs()); cmB.extras().showTabs(show);
} else {
diffTable.removeStyleName(DiffTable.style.showTabs());
}
} }
void setLineLength(int columns) { void setLineLength(int columns) {
double w = columns * getCharWidthPx(); cmA.extras().lineLength(columns);
columnMarginA.getStyle().setMarginLeft(w, Style.Unit.PX); cmB.extras().lineLength(columns);
columnMarginB.getStyle().setMarginLeft(w, Style.Unit.PX);
}
double getLineHeightPx() {
if (lineHeightPx <= 1) {
Element p = DOM.createDiv();
int lines = 1;
for (int i = 0; i < lines; i++) {
Element e = DOM.createDiv();
p.appendChild(e);
Element pre = DOM.createElement("pre");
pre.setInnerText("gqyŚŻŹŃ");
e.appendChild(pre);
}
cmB.measure().appendChild(p);
lineHeightPx = ((double) p.getOffsetHeight()) / lines;
p.removeFromParent();
}
return lineHeightPx;
}
private double getCharWidthPx() {
if (charWidthPx <= 1) {
int len = 100;
StringBuilder s = new StringBuilder();
for (int i = 0; i < len; i++) {
s.append('m');
}
Element e = DOM.createSpan();
e.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
e.setInnerText(s.toString());
cmA.measure().appendChild(e);
double a = ((double) e.getOffsetWidth()) / len;
e.removeFromParent();
cmB.measure().appendChild(e);
double b = ((double) e.getOffsetWidth()) / len;
e.removeFromParent();
charWidthPx = Math.max(a, b);
}
return charWidthPx;
} }
void setShowLineNumbers(boolean b) { void setShowLineNumbers(boolean b) {
@@ -814,15 +757,6 @@ public class SideBySide2 extends Screen {
return chunkManager.getLineMapper().lineOnOther(side, line); return chunkManager.getLineMapper().lineOnOther(side, line);
} }
private void clearActiveLine(CodeMirror cm) {
if (cm.hasActiveLine()) {
LineHandle activeLine = cm.activeLine();
cm.removeLineClass(activeLine,
LineClassWhere.WRAP, DiffTable.style.activeLine());
cm.activeLine(null);
}
}
private Runnable updateActiveLine(final CodeMirror cm) { private Runnable updateActiveLine(final CodeMirror cm) {
final CodeMirror other = otherCm(cm); final CodeMirror other = otherCm(cm);
return new Runnable() { return new Runnable() {
@@ -841,22 +775,16 @@ public class SideBySide2 extends Screen {
public void run() { public void run() {
LineHandle handle = LineHandle handle =
cm.getLineHandleVisualStart(cm.getCursor("end").line()); cm.getLineHandleVisualStart(cm.getCursor("end").line());
if (cm.hasActiveLine() && cm.activeLine().equals(handle)) { if (!cm.extras().activeLine(handle)) {
return; return;
} }
clearActiveLine(cm);
clearActiveLine(other);
cm.activeLine(handle);
cm.addLineClass(
handle, LineClassWhere.WRAP, DiffTable.style.activeLine());
LineOnOtherInfo info = LineOnOtherInfo info =
lineOnOther(cm.side(), cm.getLineNumber(handle)); lineOnOther(cm.side(), cm.getLineNumber(handle));
if (info.isAligned()) { if (info.isAligned()) {
LineHandle oLineHandle = other.getLineHandle(info.getLine()); other.extras().activeLine(other.getLineHandle(info.getLine()));
other.activeLine(oLineHandle); } else {
other.addLineClass(oLineHandle, LineClassWhere.WRAP, other.extras().clearActiveLine();
DiffTable.style.activeLine());
} }
} }
}); });
@@ -876,8 +804,8 @@ public class SideBySide2 extends Screen {
&& !clickEvent.getAltKey() && !clickEvent.getAltKey()
&& !clickEvent.getCtrlKey() && !clickEvent.getCtrlKey()
&& !clickEvent.getShiftKey()) { && !clickEvent.getShiftKey()) {
if (!(cm.hasActiveLine() && if (!(cm.extras().hasActiveLine() &&
cm.getLineNumber(cm.activeLine()) == line)) { cm.getLineNumber(cm.extras().activeLine()) == line)) {
cm.setCursor(Pos.create(line)); cm.setCursor(Pos.create(line));
} }
Scheduler.get().scheduleDeferred(new ScheduledCommand() { Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@@ -927,10 +855,10 @@ public class SideBySide2 extends Screen {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
if (cmSrc.hasActiveLine()) { if (cmSrc.extras().hasActiveLine()) {
cmDst.setCursor(Pos.create(lineOnOther( cmDst.setCursor(Pos.create(lineOnOther(
sideSrc, sideSrc,
cmSrc.getLineNumber(cmSrc.activeLine())).getLine())); cmSrc.getLineNumber(cmSrc.extras().activeLine())).getLine()));
} }
cmDst.focus(); cmDst.focus();
} }

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -39,7 +40,23 @@ public class CodeMirror extends JavaScriptObject {
Loader.initLibrary(cb); Loader.initLibrary(cb);
} }
public static native CodeMirror create(Element p, Configuration cfg) /*-{ interface Style extends CssResource {
String activeLine();
String showTabs();
String margin();
}
static Style style() {
return Lib.I.style();
}
public static CodeMirror create(Element p, Configuration cfg) {
CodeMirror cm = newCM(p, cfg);
Extras.attach(cm);
return cm;
}
private static native CodeMirror newCM(Element p, Configuration cfg) /*-{
return $wnd.CodeMirror(p, cfg); return $wnd.CodeMirror(p, cfg);
}-*/; }-*/;
@@ -257,18 +274,6 @@ public class CodeMirror extends JavaScriptObject {
return this.somethingSelected() return this.somethingSelected()
}-*/; }-*/;
public final native boolean hasActiveLine() /*-{
return !!this.state.activeLine
}-*/;
public final native LineHandle activeLine() /*-{
return this.state.activeLine
}-*/;
public final native void activeLine(LineHandle line) /*-{
this.state.activeLine = line
}-*/;
public final native void addKeyMap(KeyMap map) /*-{ this.addKeyMap(map) }-*/; public final native void addKeyMap(KeyMap map) /*-{ this.addKeyMap(map) }-*/;
public final native void removeKeyMap(KeyMap map) /*-{ this.removeKeyMap(map) }-*/; public final native void removeKeyMap(KeyMap map) /*-{ this.removeKeyMap(map) }-*/;
@@ -333,11 +338,13 @@ public class CodeMirror extends JavaScriptObject {
return this; return this;
}-*/; }-*/;
public final native DisplaySide side() /*-{ return this._sbs2_side }-*/; public final DisplaySide side() {
public final native CodeMirror side(DisplaySide side) /*-{ return extras().side();
this._sbs2_side = side; }
return this;
}-*/; public final Extras extras() {
return Extras.get(this);
}
protected CodeMirror() { protected CodeMirror() {
} }

View File

@@ -0,0 +1,143 @@
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package net.codemirror.lib;
import static com.google.gwt.dom.client.Style.Display.INLINE_BLOCK;
import static com.google.gwt.dom.client.Style.Unit.PX;
import static net.codemirror.lib.CodeMirror.style;
import static net.codemirror.lib.CodeMirror.LineClassWhere.WRAP;
import com.google.gerrit.client.diff.DisplaySide;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import net.codemirror.lib.CodeMirror.LineHandle;
import java.util.Objects;
/** Additional features added to CodeMirror by Gerrit Code Review. */
public class Extras {
static final native Extras get(CodeMirror c) /*-{ return c.gerritExtras }-*/;
private static final native void set(CodeMirror c, Extras e)
/*-{ c.gerritExtras = e }-*/;
static void attach(CodeMirror c) {
set(c, new Extras(c));
}
private final CodeMirror cm;
private Element margin;
private DisplaySide side;
private double charWidthPx;
private double lineHeightPx;
private LineHandle activeLine;
private Extras(CodeMirror cm) {
this.cm = cm;
}
public DisplaySide side() {
return side;
}
public void side(DisplaySide s) {
side = s;
}
public double charWidthPx() {
if (charWidthPx <= 1) {
int len = 100;
StringBuilder s = new StringBuilder();
for (int i = 0; i < len; i++) {
s.append('m');
}
Element e = DOM.createSpan();
e.getStyle().setDisplay(INLINE_BLOCK);
e.setInnerText(s.toString());
cm.measure().appendChild(e);
charWidthPx = ((double) e.getOffsetWidth()) / len;
e.removeFromParent();
}
return charWidthPx;
}
public double lineHeightPx() {
if (lineHeightPx <= 1) {
Element p = DOM.createDiv();
int lines = 1;
for (int i = 0; i < lines; i++) {
Element e = DOM.createDiv();
p.appendChild(e);
Element pre = DOM.createElement("pre");
pre.setInnerText("gqyŚŻŹŃ");
e.appendChild(pre);
}
cm.measure().appendChild(p);
lineHeightPx = ((double) p.getOffsetHeight()) / lines;
p.removeFromParent();
}
return lineHeightPx;
}
public void lineLength(int columns) {
if (margin == null) {
margin = DOM.createDiv();
margin.setClassName(style().margin());
cm.mover().appendChild(margin);
}
margin.getStyle().setMarginLeft(columns * charWidthPx(), PX);
}
public void showTabs(boolean show) {
Element e = cm.getWrapperElement();
if (show) {
e.addClassName(style().showTabs());
} else {
e.removeClassName(style().showTabs());
}
}
public final boolean hasActiveLine() {
return activeLine != null;
}
public final LineHandle activeLine() {
return activeLine;
}
public final boolean activeLine(LineHandle line) {
if (Objects.equals(activeLine, line)) {
return false;
}
if (activeLine != null) {
cm.removeLineClass(activeLine, WRAP, style().activeLine());
}
activeLine = line;
cm.addLineClass(activeLine, WRAP, style().activeLine());
return true;
}
public final void clearActiveLine() {
if (activeLine != null) {
cm.removeLineClass(activeLine, WRAP, style().activeLine());
activeLine = null;
}
}
}

View File

@@ -29,4 +29,7 @@ interface Lib extends ClientBundle {
@Source("cm.js") @Source("cm.js")
@DoNotEmbed @DoNotEmbed
DataResource js(); DataResource js();
@Source("style.css")
CodeMirror.Style style();
} }

View File

@@ -56,6 +56,7 @@ public class Loader {
@Override @Override
public void onSuccess(TextResource resource) { public void onSuccess(TextResource resource) {
StyleInjector.inject(resource.getText()); StyleInjector.inject(resource.getText());
Lib.I.style().ensureInjected();
cb.onSuccess(null); cb.onSuccess(null);
} }

View File

@@ -0,0 +1,83 @@
/* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@external .CodeMirror;
@external .CodeMirror-lines;
@external .CodeMirror-linenumber;
@external .CodeMirror-overlayscroll-horizontal;
@external .CodeMirror-overlayscroll-vertical;
@external .cm-tab;
@external .cm-searching;
@external .cm-trailingspace;
/* Reduce margins around CodeMirror to save space. */
.CodeMirror-lines {
padding: 0;
}
.CodeMirror pre {
padding: 0;
line-height: normal;
}
/* Minimum scrollbar bubble size even on large files. */
.CodeMirror-overlayscroll-horizontal div {
min-width: 25px;
}
.CodeMirror-overlayscroll-vertical div {
min-height: 25px;
}
/* Stack the scrollbar so annotations can receive clicks. */
.CodeMirror-overlayscroll-vertical {
z-index: inherit;
}
.CodeMirror-overlayscroll-horizontal div,
.CodeMirror-overlayscroll-vertical div {
background-color: rgba(128, 128, 128, 0.50);
z-index: 8;
}
/* Highlight current line number in the line gutter. */
.activeLine .CodeMirror-linenumber {
background-color: #bcf !important;
color: #000;
}
.showTabs .cm-tab:before {
position: absolute;
content: "\00bb";
color: #f00;
}
.cm-searching {
background-color: #ffa;
}
.cm-trailingspace {
background-color: red;
}
/* Line length margin displayed at NN columns to provide
* a visual guide for length of any single line of code.
*/
.margin {
position: absolute;
top: 0;
bottom: 0;
width: 0;
border-right: 1px dashed #ffa500;
z-index: 2;
cursor: text;
}