diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java index 17bacc68a6..e4ddebdc85 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java @@ -37,6 +37,7 @@ class DiffTable extends Composite { private static final Binder uiBinder = GWT.create(Binder.class); interface DiffTableStyle extends CssResource { + String insertCommentIcon(); String fullscreen(); String intralineBg(); String diff(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml index 05ea3669df..f314849a90 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.ui.xml @@ -23,6 +23,11 @@ limitations under the License. @external .cm-keymap-fat-cursor, CodeMirror-cursor; @external .cm-searching, .cm-trailingspace, .cm-tab; + .insertCommentIcon { + cursor: pointer; + position: absolute; + z-index: 150; + } .fullscreen { background-color: #f7f7f7; border-bottom: 1px solid #ddd; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java index f6fca9744b..7d16915bb0 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java @@ -54,7 +54,10 @@ 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; +import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.logical.shared.ResizeEvent; @@ -65,6 +68,7 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.globalkey.client.GlobalKey; @@ -73,6 +77,7 @@ import com.google.gwtexpui.globalkey.client.KeyCommandSet; import com.google.gwtexpui.globalkey.client.ShowHelpCommand; import net.codemirror.lib.CodeMirror; +import net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler; import net.codemirror.lib.CodeMirror.GutterClickHandler; import net.codemirror.lib.CodeMirror.LineClassWhere; import net.codemirror.lib.CodeMirror.LineHandle; @@ -83,6 +88,7 @@ import net.codemirror.lib.KeyMap; import net.codemirror.lib.LineCharacter; import net.codemirror.lib.LineWidget; import net.codemirror.lib.ModeInjector; +import net.codemirror.lib.Rect; import net.codemirror.lib.TextMarker; import net.codemirror.lib.TextMarker.FromTo; @@ -314,6 +320,7 @@ public class SideBySide2 extends Screen { } private void registerCmEvents(final CodeMirror cm) { + cm.on("beforeSelectionChange", onSelectionChange(cm)); cm.on("cursorActivity", updateActiveLine(cm)); cm.on("gutterClick", onGutterClick(cm)); cm.on("renderLine", resizeLinePadding(getSideFromCm(cm))); @@ -399,6 +406,47 @@ public class SideBySide2 extends Screen { .on("Shift-Right", flipCursorSide(cm, false))); } + private BeforeSelectionChangeHandler onSelectionChange(final CodeMirror cm) { + return new BeforeSelectionChangeHandler() { + private Image icon; + + @Override + public void handle(CodeMirror cm, LineCharacter anchor, LineCharacter head) { + if (anchor == head + || (anchor.getLine() == head.getLine() + && anchor.getCh() == head.getCh())) { + if (icon != null) { + icon.setVisible(false); + } + return; + } else if (icon == null) { + init(anchor); + } + + icon.setVisible(true); + Rect r = cm.charCoords(head, "local"); + Style s = icon.getElement().getStyle(); + s.setTop((int) (r.top() - icon.getOffsetHeight() + 2), Unit.PX); + s.setLeft((int) (r.right() - icon.getOffsetWidth() / 2), Unit.PX); + } + + private void init(LineCharacter anchor) { + icon = new Image(Gerrit.RESOURCES.draftComments()); + icon.setTitle(PatchUtil.C.commentInsert()); + icon.setStyleName(DiffTable.style.insertCommentIcon()); + icon.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + icon.setVisible(false); + insertNewDraft(cm).run(); + } + }); + add(icon); + cm.addWidget(anchor, icon.getElement(), false); + } + }; + } + @Override public void registerKeys() { super.registerKeys(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java index 0f9a5cb19e..4adb9cc6de 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SkipBar.java @@ -133,6 +133,7 @@ class SkipBar extends Composite { void expandAll() { clearMarkerAndWidget(); removeFromParent(); + updateSelection(); } private void expandBefore() { @@ -148,6 +149,7 @@ class SkipBar extends Composite { .set("noHScroll", true); setWidget(cm.addLineWidget(newStart - 1, getElement(), config)); updateSkipNum(); + updateSelection(); } private void expandAfter() { @@ -167,6 +169,14 @@ class SkipBar extends Composite { setWidget(cm.addLineWidget(newEnd + 1, getElement(), config)); } updateSkipNum(); + updateSelection(); + } + + private void updateSelection() { + if (cm.somethingSelected()) { + FromTo sel = cm.getSelectedRange(); + cm.setSelection(sel.getFrom(), sel.getTo()); + } } @UiHandler("skipNum") diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java index 28f5096c7a..712f268fd0 100644 --- a/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java +++ b/gerrit-gwtui/src/main/java/net/codemirror/lib/CodeMirror.java @@ -138,6 +138,10 @@ public class CodeMirror extends JavaScriptObject { return this.heightAtLine(line, mode); }-*/; + public final native Rect charCoords(LineCharacter pos, String mode) /*-{ + return this.charCoords(pos, mode); + }-*/; + public final native CodeMirrorDoc getDoc() /*-{ return this.getDoc(); }-*/; @@ -197,6 +201,12 @@ public class CodeMirror extends JavaScriptObject { })); }-*/; + public final native void on(String event, BeforeSelectionChangeHandler handler) /*-{ + this.on(event, $entry(function(cm, e) { + handler.@net.codemirror.lib.CodeMirror.BeforeSelectionChangeHandler::handle(Lnet/codemirror/lib/CodeMirror;Lnet/codemirror/lib/LineCharacter;Lnet/codemirror/lib/LineCharacter;)(cm,e.anchor,e.head); + })); + }-*/; + public final native LineCharacter getCursor() /*-{ return this.getCursor(); }-*/; @@ -209,8 +219,12 @@ public class CodeMirror extends JavaScriptObject { return FromTo.create(getCursor("start"), getCursor("end")); } - public final native void setSelection(LineCharacter lineCh) /*-{ - this.setSelection(lineCh); + public final native void setSelection(LineCharacter anchor) /*-{ + this.setSelection(anchor); + }-*/; + + public final native void setSelection(LineCharacter anchor, LineCharacter head) /*-{ + this.setSelection(anchor, head); }-*/; public final native void setCursor(LineCharacter lineCh) /*-{ @@ -345,4 +359,8 @@ public class CodeMirror extends JavaScriptObject { public void handle(CodeMirror instance, int line, String gutter, NativeEvent clickEvent); } + + public interface BeforeSelectionChangeHandler { + public void handle(CodeMirror instance, LineCharacter anchor, LineCharacter head); + } } diff --git a/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java b/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java new file mode 100644 index 0000000000..5691d9f298 --- /dev/null +++ b/gerrit-gwtui/src/main/java/net/codemirror/lib/Rect.java @@ -0,0 +1,28 @@ +// Copyright (C) 2013 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 com.google.gwt.core.client.JavaScriptObject; + +/** {left, right, top, bottom} objects used within CodeMirror. */ +public class Rect extends JavaScriptObject { + public final native double left() /*-{ return this.left }-*/; + public final native double right() /*-{ return this.right }-*/; + public final native double top() /*-{ return this.top }-*/; + public final native double bottom() /*-{ return this.bottom }-*/; + + protected Rect() { + } +}