Merge "Merge branch 'stable-2.10'"
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
index 2ef12e3..fb2d250 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.java
@@ -192,11 +192,9 @@
   @UiField Button addFile;
   @UiField Button expandAll;
   @UiField Button collapseAll;
-  @UiField Button editMessage;
   @UiField QuickApprove quickApprove;
 
   private ReplyAction replyAction;
-  private EditMessageAction editMessageAction;
   private IncludedInAction includedInAction;
   private PatchSetsAction patchSetsAction;
   private DownloadAction downloadAction;
@@ -524,27 +522,6 @@
     return currentPatchSetOrEdit == 0;
   }
 
-  private void initEditMessageAction(ChangeInfo info, String revision) {
-    RevisionInfo revisionInfo = info.revision(revision);
-    NativeMap<ActionInfo> actions = revisionInfo.actions();
-    if ((actions != null && actions.containsKey("message"))
-        || revisionInfo.is_edit()) {
-      editMessage.setVisible(true);
-      editMessageAction = new EditMessageAction(
-          info.legacy_id(),
-          revisionInfo.commit().message(),
-          style,
-          editMessage,
-          reply);
-      keysAction.add(new KeyCommand(0, 'e', Util.C.keyEditMessage()) {
-        @Override
-        public void onKeyPress(KeyPressEvent event) {
-          editMessageAction.onEdit();
-        }
-      });
-    }
-  }
-
   @UiHandler("publishEdit")
   void onPublishEdit(@SuppressWarnings("unused") ClickEvent e) {
     EditActions.publishEdit(changeId);
@@ -685,11 +662,6 @@
     }
   }
 
-  @UiHandler("editMessage")
-  void onEditMessage(@SuppressWarnings("unused") ClickEvent e) {
-    editMessageAction.onEdit();
-  }
-
   @UiHandler("openAll")
   void onOpenAll(@SuppressWarnings("unused") ClickEvent e) {
     files.openAll();
@@ -800,7 +772,7 @@
       files.set(
           b != null ? new PatchSet.Id(changeId, b._number()) : null,
           new PatchSet.Id(changeId, rev._number()),
-          style, editMessage, reply, fileTableMode, edit != null);
+          style, reply, fileTableMode, edit != null);
       files.setValue(info.edit().files(), myLastReply(info), emptyComment,
           emptyComment);
     } else {
@@ -853,7 +825,7 @@
           files.set(
               base != null ? new PatchSet.Id(changeId, base._number()) : null,
               new PatchSet.Id(changeId, rev._number()),
-              style, editMessage, reply, fileTableMode, edit != null);
+              style, reply, fileTableMode, edit != null);
           files.setValue(m, myLastReply, comments.get(0), drafts.get(0));
         }
 
@@ -1093,7 +1065,6 @@
     }
 
     if (Gerrit.isSignedIn()) {
-      initEditMessageAction(info, revision);
       replyAction = new ReplyAction(info, revision,
           style, commentLinkProcessor, reply, quickApprove);
       if (topic.canEdit()) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
index cecf5b3..7d13aff 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen2.ui.xml
@@ -58,12 +58,6 @@
       text-overflow: ellipsis;
       white-space: nowrap;
     }
-    .subjectButtons {
-      position: absolute;
-      top: 0;
-      right: 3px;
-      height: HEADER_HEIGHT;
-    }
 
     .infoLine {
       position: absolute;
@@ -340,15 +334,6 @@
             </g:Anchor> - <span ui:field='statusText' class='{style.statusText}'/></ui:msg>
           </span>
         </div>
-        <div class='{style.subjectButtons} {style.headerButtons}'>
-          <g:Button ui:field='editMessage'
-              styleName=''
-              visible='false'
-              title='Edit commit message (Shortcut: e)'>
-            <ui:attribute name='title'/>
-            <div><ui:msg>Edit Message</ui:msg></div>
-          </g:Button>
-        </div>
       </div>
 
       <div class='{style.infoLine}'>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageAction.java
deleted file mode 100644
index 61a6805..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageAction.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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 com.google.gerrit.client.change;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.user.client.PluginSafePopupPanel;
-
-class EditMessageAction {
-  private final Change.Id changeId;
-  private final String originalMessage;
-  private final ChangeScreen2.Style style;
-  private final Widget editMessageButton;
-  private final Widget replyButton;
-
-  private EditMessageBox editBox;
-  private PopupPanel popup;
-
-  EditMessageAction(
-      Change.Id changeId,
-      String originalMessage,
-      ChangeScreen2.Style style,
-      Widget editButton,
-      Widget replyButton) {
-    this.changeId = changeId;
-    this.originalMessage = originalMessage;
-    this.style = style;
-    this.editMessageButton = editButton;
-    this.replyButton = replyButton;
-  }
-
-  void onEdit() {
-    if (popup != null) {
-      popup.hide();
-      return;
-    }
-
-    if (editBox == null) {
-      editBox = new EditMessageBox(
-          changeId,
-          originalMessage);
-    }
-
-    final PluginSafePopupPanel p = new PluginSafePopupPanel(true);
-    p.setStyleName(style.replyBox());
-    p.addAutoHidePartner(editMessageButton.getElement());
-    p.addCloseHandler(new CloseHandler<PopupPanel>() {
-      @Override
-      public void onClose(CloseEvent<PopupPanel> event) {
-        if (popup == p) {
-          popup = null;
-        }
-      }
-    });
-    p.add(editBox);
-    p.showRelativeTo(replyButton);
-    GlobalKey.dialog(p);
-    popup = p;
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.java
deleted file mode 100644
index 317e9ac..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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 com.google.gerrit.client.change;
-
-import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.VoidResult;
-import com.google.gerrit.client.changes.ChangeEditApi;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.TextBoxChangeListener;
-import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.uibinder.client.UiHandler;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-
-class EditMessageBox extends Composite {
-  interface Binder extends UiBinder<HTMLPanel, EditMessageBox> {}
-  private static final Binder uiBinder = GWT.create(Binder.class);
-
-  private final Change.Id changeId;
-  private String originalMessage;
-
-  @UiField NpTextArea message;
-  @UiField Button save;
-  @UiField Button cancel;
-
-  EditMessageBox(
-      Change.Id changeId,
-      String msg) {
-    this.changeId = changeId;
-    this.originalMessage = msg.trim();
-    initWidget(uiBinder.createAndBindUi(this));
-    message.getElement().setAttribute("wrap", "off");
-    message.setText("");
-    new TextBoxChangeListener(message) {
-      @Override
-      public void onTextChanged(String newText) {
-        save.setEnabled(!newText.trim()
-            .equals(originalMessage));
-      }
-    };
-  }
-
-  @Override
-  protected void onLoad() {
-    if (message.getText().isEmpty()) {
-      message.setText(originalMessage);
-      save.setEnabled(false);
-    }
-    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
-      @Override
-      public void execute() {
-        message.setFocus(true);
-      }});
-  }
-
-  @UiHandler("save")
-  void onSave(@SuppressWarnings("unused") ClickEvent e) {
-    save.setEnabled(false);
-    ChangeEditApi.putMessage(changeId.get(), message.getText().trim(),
-        new GerritCallback<VoidResult>() {
-          @Override
-          public void onSuccess(VoidResult result) {
-            Gerrit.display(PageLinks.toChangeInEditMode(changeId));
-            hide();
-          }
-        });
-  }
-
-  @UiHandler("cancel")
-  void onCancel(@SuppressWarnings("unused") ClickEvent e) {
-    message.setText("");
-    hide();
-  }
-
-  protected void hide() {
-    for (Widget w = getParent(); w != null; w = w.getParent()) {
-      if (w instanceof PopupPanel) {
-        ((PopupPanel) w).hide();
-        break;
-      }
-    }
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.ui.xml
deleted file mode 100644
index 9df4bbc..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditMessageBox.ui.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<ui:UiBinder
-    xmlns:ui='urn:ui:com.google.gwt.uibinder'
-    xmlns:g='urn:import:com.google.gwt.user.client.ui'
-    xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'>
-  <ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
-  <ui:style>
-    .commitMessage {
-      background-color: white;
-      font-family: monospace;
-    }
-    .cancel { float: right; }
-  </ui:style>
-  <g:HTMLPanel>
-    <div class='{res.style.section}'>
-      <c:NpTextArea
-         visibleLines='30'
-         characterWidth='78'
-         styleName='{style.commitMessage}'
-         ui:field='message'/>
-    </div>
-    <div class='{res.style.section}'>
-      <g:Button ui:field='save'
-          title='Create new patch set with updated commit message'
-          styleName='{res.style.button}'>
-        <ui:attribute name='title'/>
-        <div><ui:msg>Save</ui:msg></div>
-      </g:Button>
-      <g:Button ui:field='cancel'
-          styleName='{res.style.button}'
-          addStyleNames='{style.cancel}'>
-          <div>Cancel</div>
-      </g:Button>
-    </div>
-  </g:HTMLPanel>
-</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java
index c0fe3e0..f5a80ba 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java
@@ -180,7 +180,6 @@
   private JsArrayString reviewed;
   private String scrollToPath;
   private ChangeScreen2.Style style;
-  private Widget editButton;
   private Widget replyButton;
   private boolean editExists;
   private Mode mode;
@@ -192,11 +191,10 @@
   }
 
   public void set(PatchSet.Id base, PatchSet.Id curr, ChangeScreen2.Style style,
-      Widget editButton, Widget replyButton, Mode mode, boolean editExists) {
+      Widget replyButton, Mode mode, boolean editExists) {
     this.base = base;
     this.curr = curr;
     this.style = style;
-    this.editButton = editButton;
     this.replyButton = replyButton;
     this.mode = mode;
     this.editExists = editExists;
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 10b2640..4bd08b1 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
@@ -75,8 +75,6 @@
 
   private SideBySide2 parent;
   private boolean header;
-  private boolean headerVisible;
-  private boolean autoHideHeader;
   private boolean visibleA;
   private ChangeType changeType;
 
@@ -91,7 +89,6 @@
     initWidget(uiBinder.createAndBindUi(this));
     this.scrollbar = new Scrollbar(this);
     this.parent = parent;
-    this.headerVisible = true;
     this.visibleA = true;
   }
 
@@ -127,30 +124,16 @@
     }
   }
 
-  boolean isHeaderVisible() {
-    return headerVisible;
-  }
-
   void setHeaderVisible(boolean show) {
-    headerVisible = !autoHideHeader || show;
-    showHeader(headerVisible);
-  }
-
-  private void showHeader(boolean show) {
-    UIObject.setVisible(patchSetNavRow, show);
-    UIObject.setVisible(diffHeaderRow, show && header);
-    if (show) {
-      parent.header.removeStyleName(style.fullscreen());
-    } else {
-      parent.header.addStyleName(style.fullscreen());
-    }
-    parent.resizeCodeMirror();
-  }
-
-  void setAutoHideDiffHeader(boolean hide) {
-    autoHideHeader = hide;
-    if (!hide) {
-      showHeader(true);
+    if (show != UIObject.isVisible(patchSetNavRow)) {
+      UIObject.setVisible(patchSetNavRow, show);
+      UIObject.setVisible(diffHeaderRow, show && header);
+      if (show) {
+        parent.header.removeStyleName(style.fullscreen());
+      } else {
+        parent.header.addStyleName(style.fullscreen());
+      }
+      parent.resizeCodeMirror();
     }
   }
 
@@ -169,7 +152,6 @@
   void set(DiffPreferences prefs, JsArray<RevisionInfo> list, DiffInfo info,
       boolean editExists, int currentPatchSet, boolean open) {
     this.changeType = info.change_type();
-    this.autoHideHeader = prefs.autoHideDiffTableHeader();
     patchSetSelectBoxA.setUpPatchSetNav(list, info.meta_a(), editExists,
         currentPatchSet, open);
     patchSetSelectBoxB.setUpPatchSetNav(list, info.meta_b(), editExists,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
index 70bde00..433ce5e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PreferencesBox.java
@@ -334,7 +334,6 @@
   void onAutoHideDiffTableHeader(ValueChangeEvent<Boolean> e) {
     prefs.autoHideDiffTableHeader(!e.getValue());
     view.setAutoHideDiffHeader(!e.getValue());
-    view.resizeCodeMirror();
   }
 
   @UiHandler("manualReview")
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java
index 61e00c3..4ee09d2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/ScrollSynchronizer.java
@@ -25,12 +25,15 @@
   private ScrollCallback active;
   private ScrollCallback callbackA;
   private ScrollCallback callbackB;
+  private CodeMirror cmB;
+  private boolean autoHideDiffTableHeader;
 
   ScrollSynchronizer(DiffTable diffTable,
       CodeMirror cmA, CodeMirror cmB,
       LineMapper mapper) {
     this.diffTable = diffTable;
     this.mapper = mapper;
+    this.cmB = cmB;
 
     callbackA = new ScrollCallback(cmA, cmB, DisplaySide.A);
     callbackB = new ScrollCallback(cmB, cmA, DisplaySide.B);
@@ -38,15 +41,23 @@
     cmB.on("scroll", callbackB);
   }
 
+  void setAutoHideDiffTableHeader(boolean autoHide) {
+    if (autoHide) {
+      updateDiffTableHeader(cmB.getScrollInfo());
+    } else {
+      diffTable.setHeaderVisible(true);
+    }
+    autoHideDiffTableHeader = autoHide;
+  }
+
   void syncScroll(DisplaySide masterSide) {
     (masterSide == DisplaySide.A ? callbackA : callbackB).sync();
   }
 
-  private void updateScreenHeader(ScrollInfo si) {
-    if (si.top() == 0 && !diffTable.isHeaderVisible()) {
+  private void updateDiffTableHeader(ScrollInfo si) {
+    if (si.top() == 0) {
       diffTable.setHeaderVisible(true);
-    } else if (si.top() > 0.5 * si.clientHeight()
-        && diffTable.isHeaderVisible()) {
+    } else if (si.top() > 0.5 * si.clientHeight()) {
       diffTable.setHeaderVisible(false);
     }
   }
@@ -84,7 +95,9 @@
       }
       if (active == this) {
         ScrollInfo si = src.getScrollInfo();
-        updateScreenHeader(si);
+        if (autoHideDiffTableHeader) {
+          updateDiffTableHeader(si);
+        }
         dst.scrollTo(si.left(), align(si.top()));
         state = 0;
       }
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 5195024..75e0d90 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
@@ -603,6 +603,7 @@
 
     prefsAction = new PreferencesAction(this, prefs);
     header.init(prefsAction, getLinks(), diff.side_by_side_web_links());
+    scrollSynchronizer.setAutoHideDiffTableHeader(prefs.autoHideDiffTableHeader());
 
     if (prefs.syntaxHighlighting() && fileSize.compareTo(FileSize.SMALL) > 0) {
       Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
@@ -757,7 +758,7 @@
   }
 
   void setAutoHideDiffHeader(boolean hide) {
-    diffTable.setAutoHideDiffHeader(hide);
+    scrollSynchronizer.setAutoHideDiffTableHeader(hide);
   }
 
   private void render(DiffInfo diff) {