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; +}