Allow in preview diff screens to select patch sets to be compared
Similar to the normal diff screens the preview diff screens have now a
header that shows the patch sets so that the user can change the
patch sets that are compared.
Change-Id: Ibb9d87ef8ee301170586f2b4b533ca086a04144d
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/ChangeInfo.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/ChangeInfo.java
index 9aece0a..d02913e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/ChangeInfo.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/ChangeInfo.java
@@ -15,7 +15,12 @@
package com.googlesource.gerrit.plugins.xdocs.client;
import com.google.gerrit.client.rpc.NativeMap;
+import com.google.gerrit.client.rpc.Natives;
import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
+
+import java.util.Collections;
+import java.util.Comparator;
public class ChangeInfo extends JavaScriptObject {
public final native String project() /*-{ return this.project; }-*/;
@@ -28,7 +33,44 @@
public static class RevisionInfo extends JavaScriptObject {
public final native int _number() /*-{ return this._number; }-*/;
+ public final native String name() /*-{ return this.name; }-*/;
public final native String ref() /*-{ return this.ref; }-*/;
+ public final native boolean is_edit() /*-{ return this._number == 0; }-*/;
+ public final native String edit_base() /*-{ return this.edit_base; }-*/;
+
+ public static int findEditParent(JsArray<RevisionInfo> list) {
+ for (int i = 0; i < list.length(); i++) {
+ // edit under revisions?
+ RevisionInfo editInfo = list.get(i);
+ if (editInfo.is_edit()) {
+ String parentRevision = editInfo.edit_base();
+ // find parent
+ for (int j = 0; j < list.length(); j++) {
+ RevisionInfo parentInfo = list.get(j);
+ String name = parentInfo.name();
+ if (name.equals(parentRevision)) {
+ // found parent patch set number
+ return parentInfo._number();
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static void sortRevisionInfoByNumber(JsArray<RevisionInfo> list) {
+ final int editParent = findEditParent(list);
+ Collections.sort(Natives.asList(list), new Comparator<RevisionInfo>() {
+ @Override
+ public int compare(RevisionInfo a, RevisionInfo b) {
+ return num(a) - num(b);
+ }
+
+ private int num(RevisionInfo r) {
+ return !r.is_edit() ? 2 * (r._number() - 1) + 1 : 2 * editParent;
+ }
+ });
+ }
protected RevisionInfo () {
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/PatchSetSelectBox.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/PatchSetSelectBox.java
new file mode 100644
index 0000000..8ced54b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/PatchSetSelectBox.java
@@ -0,0 +1,160 @@
+// 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 com.googlesource.gerrit.plugins.xdocs.client;
+
+import com.google.gerrit.plugin.client.Plugin;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.http.client.URL;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.InlineHyperlink;
+import com.google.gwt.user.client.ui.Label;
+
+import com.googlesource.gerrit.plugins.xdocs.client.ChangeInfo.RevisionInfo;
+
+public class PatchSetSelectBox extends FlowPanel {
+
+ public enum DisplaySide {
+ A, B
+ }
+
+ public static enum DiffView {
+ SIDE_BY_SIDE,
+ UNIFIED_DIFF
+ }
+
+ private final DiffView diffView;
+ private final DisplaySide side;
+ private final ChangeInfo change;
+ private final Integer basePatchSet;
+ private final int patchSet;
+ private final String path;
+
+ public PatchSetSelectBox(DiffView diffView, DisplaySide side,
+ ChangeInfo change, Integer basePatchSet, int patchSet, String path) {
+ this.diffView = diffView;
+ this.side = side;
+ this.change = change;
+ this.path = path;
+ this.basePatchSet = basePatchSet;
+ this.patchSet = patchSet;
+
+ init();
+ }
+
+ private void init() {
+ setStyleName("xdocs-patch-set-select-box");
+ if (isSideBySideDiff()) {
+ addStyleName("xdocs-patch-set-select-box-side-by-side");
+ }
+
+ addPatchSetLabel();
+
+ if (sideA()) {
+ add(createBaseLink());
+ } else if (isUnifiedDiff()) {
+ // create hidden 'Base' link to align the patch set links with side A
+ add(createHiddenBaseLink());
+ }
+
+ JsArray<RevisionInfo> list = change.revisions().values();
+ RevisionInfo.sortRevisionInfoByNumber(list);
+ for (int i = 0; i < list.length(); i++) {
+ add(createLink(list.get(i)));
+ }
+ }
+
+ private void addPatchSetLabel() {
+ add(new Label("Patch Set"));
+ if (isUnifiedDiff()) {
+ Label l = new Label(sideA() ? "(-)" : "(+)");
+ l.addStyleName("xdocs-monospace");
+ add(l);
+ }
+ }
+
+ private boolean isSideBySideDiff() {
+ return diffView == DiffView.SIDE_BY_SIDE;
+ }
+
+ private boolean isUnifiedDiff() {
+ return diffView == DiffView.UNIFIED_DIFF;
+ }
+
+ private boolean sideA() {
+ return side == DisplaySide.A;
+ }
+
+ private InlineHyperlink createBaseLink() {
+ InlineHyperlink link = new InlineHyperlink("Base",
+ getUrl(change._number(), null, patchSet, path, diffView));
+ if (isBaseSelected()) {
+ link.setStyleName("xdocs-patch-set-select-box-selected");
+ }
+ return link;
+ }
+
+ private InlineHyperlink createHiddenBaseLink() {
+ InlineHyperlink link = new InlineHyperlink("Base", null);
+ link.addStyleName("xdocs-hidden");
+ return link;
+ }
+
+ private InlineHyperlink createLink(RevisionInfo r) {
+ String label = r.is_edit() ? "edit" : Integer.toString(r._number());
+ Integer patchSetIdA = sideA() ? Integer.valueOf(r._number()) : basePatchSet;
+ int patchSetIdB = sideA() ? patchSet : r._number();
+ InlineHyperlink link = new InlineHyperlink(label,
+ getUrl(change._number(), patchSetIdA, patchSetIdB, path, diffView));
+ if (isSelected(r._number())) {
+ link.setStyleName("xdocs-patch-set-select-box-selected");
+ }
+ return link;
+ }
+
+ private Integer getSelectedPatchSet() {
+ return sideA() ? basePatchSet : Integer.valueOf(patchSet);
+ }
+
+ private boolean isBaseSelected() {
+ return getSelectedPatchSet() == null;
+ }
+
+ private boolean isSelected(int ps) {
+ return getSelectedPatchSet() != null
+ && getSelectedPatchSet().intValue() == ps;
+ }
+
+ private static String getUrl(int changeId, Integer patchSetIdA,
+ int patchSetIdB, String path, DiffView diffView) {
+ StringBuilder url = new StringBuilder();
+ url.append("/x/");
+ url.append(Plugin.get().getName());
+ url.append("/c/");
+ url.append(changeId);
+ url.append("/");
+ if (patchSetIdA != null) {
+ url.append(patchSetIdA);
+ url.append("..");
+ }
+ url.append(patchSetIdB);
+ url.append("/");
+ url.append(URL.encode(path));
+ if (diffView == DiffView.UNIFIED_DIFF) {
+ url.append(",unified");
+ }
+ return url.toString();
+ }
+
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocDiffScreen.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocDiffScreen.java
index 59fef0c..8f308cb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocDiffScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocDiffScreen.java
@@ -21,6 +21,7 @@
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHyperlink;
@@ -277,4 +278,10 @@
l.setStyleName("xdocs-error");
add(l);
}
+
+ protected static int addRow(FlexTable table) {
+ int row = table.getRowCount();
+ table.insertRow(row);
+ return row;
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocSideBySideDiffScreen.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocSideBySideDiffScreen.java
index 3e57b4e..d96c6ab 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocSideBySideDiffScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocSideBySideDiffScreen.java
@@ -16,8 +16,11 @@
import com.google.gerrit.plugin.client.screen.Screen;
import com.google.gwt.http.client.URL;
+import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Frame;
-import com.google.gwt.user.client.ui.HorizontalPanel;
+
+import com.googlesource.gerrit.plugins.xdocs.client.PatchSetSelectBox.DiffView;
+import com.googlesource.gerrit.plugins.xdocs.client.PatchSetSelectBox.DisplaySide;
public class XDocSideBySideDiffScreen extends XDocDiffScreen {
static class Factory implements Screen.EntryPoint {
@@ -50,12 +53,17 @@
frameB.getElement().setId(frameIdB);
XDocScreen.resize(frameB, frameIdB);
- HorizontalPanel p = new HorizontalPanel();
- p.setVerticalAlignment(ALIGN_MIDDLE);
- p.setStyleName("xdocs-sidebyside-panel");
- p.add(frameA);
- p.add(frameB);
- add(p);
+ FlexTable t = new FlexTable();
+ t.setStyleName("xdocs-diff-table");
+ int row = addRow(t);
+ t.setWidget(row, 0, new PatchSetSelectBox(
+ DiffView.SIDE_BY_SIDE, DisplaySide.A, change, base, patchSet, path));
+ t.setWidget(row, 1, new PatchSetSelectBox(
+ DiffView.SIDE_BY_SIDE, DisplaySide.B, change, base, patchSet, path));
+ row = addRow(t);
+ t.setWidget(row, 0, frameA);
+ t.setWidget(row, 1, frameB);
+ add(t);
}
private String getRevisionSideA() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocUnifiedDiffScreen.java b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocUnifiedDiffScreen.java
index d1c6548..f97f527 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocUnifiedDiffScreen.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/client/XDocUnifiedDiffScreen.java
@@ -16,8 +16,12 @@
import com.google.gerrit.plugin.client.screen.Screen;
import com.google.gwt.http.client.URL;
+import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Frame;
+import com.googlesource.gerrit.plugins.xdocs.client.PatchSetSelectBox.DiffView;
+import com.googlesource.gerrit.plugins.xdocs.client.PatchSetSelectBox.DisplaySide;
+
public class XDocUnifiedDiffScreen extends XDocDiffScreen {
static class Factory implements Screen.EntryPoint {
@Override
@@ -41,7 +45,16 @@
new Frame(XDocApi.getUrl(change.project(), getRevision(), getPath()));
frame.getElement().setId(frameId);
XDocScreen.resize(frame, frameId);
- add(frame);
+
+ FlexTable t = new FlexTable();
+ t.setStyleName("xdocs-diff-table");
+ t.addStyleName("xdocs-unified-diff-table");
+ t.setWidget(addRow(t), 0, new PatchSetSelectBox(
+ DiffView.UNIFIED_DIFF, DisplaySide.A, change, base, patchSet, path));
+ t.setWidget(addRow(t), 0, new PatchSetSelectBox(
+ DiffView.UNIFIED_DIFF, DisplaySide.B, change, base, patchSet, path));
+ t.setWidget(addRow(t), 0, frame);
+ add(t);
}
private String getRevision() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/xdocs/public/xdocs.css b/src/main/java/com/googlesource/gerrit/plugins/xdocs/public/xdocs.css
index cc538e2..b04ffd3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/xdocs/public/xdocs.css
+++ b/src/main/java/com/googlesource/gerrit/plugins/xdocs/public/xdocs.css
@@ -49,16 +49,61 @@
font-weight: bold;
}
-.xdocs-sidebyside-panel {
+.xdocs-patch-set-select-box {
+ background-color: #F7F7F7;
+ color: #353535;
+ font-size: 12px;
+ white-space: normal;
+ font-family: sans-serif;
+ font-weight: bold;
+}
+.xdocs-patch-set-select-box-side-by-side {
+ text-align: center;
+}
+.xdocs-patch-set-select-box div {
+ padding-left: 3px;
+ padding-right: 3px;
+ vertical-align: middle;
+ display: inline-block;
+}
+.xdocs-patch-set-select-box a {
+ padding-left: 3px;
+ padding-right: 3px;
+ text-decoration: none;
+ vertical-align: middle;
+ display: inline-block;
+}
+
+.xdocs-patch-set-select-box-selected {
+ font-weight: bold;
+ background-color: #D8EDF9;
+}
+
+.xdocs-diff-table {
width: 100%;
+ color: #DDD;
border-collapse: collapse;
}
-.xdocs-sidebyside-panel td {
+.xdocs-diff-table tr:first-child td,
+.xdocs-unified-diff-table tr:nth-child(2) td {
+ color: #F7F7F7;
+}
+
+.xdocs-diff-table td {
+ padding: 0px;
border-width: 1px;
border-style: solid;
}
-.xdocs-sidebyside-panel iframe {
+.xdocs-diff-table iframe {
border-style: none;
}
+
+.xdocs-monospace {
+ font-family: monospace;
+}
+
+.xdocs-hidden {
+ visibility: hidden;
+}