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 580575cca5..498b9c244a 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 @@ -46,7 +46,6 @@ import com.google.gerrit.client.ui.ChangeLink; import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.client.ui.Screen; import com.google.gerrit.client.ui.UserActivityMonitor; -import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.changes.ListChangesOption; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; @@ -57,7 +56,6 @@ import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.Element; -import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.logical.shared.CloseEvent; @@ -72,10 +70,8 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; -import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.ToggleButton; -import com.google.gwt.user.client.ui.UIObject; import com.google.gwtexpui.clippy.client.CopyableLabel; import com.google.gwtexpui.globalkey.client.GlobalKey; import com.google.gwtexpui.globalkey.client.KeyCommand; @@ -84,7 +80,6 @@ import com.google.gwtorm.client.KeyUtil; import java.sql.Timestamp; import java.util.ArrayList; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -139,14 +134,13 @@ public class ChangeScreen2 extends Screen { @UiField Element actionDate; @UiField Actions actions; - @UiField Element revisionParent; - @UiField ListBox revisionList; @UiField Labels labels; @UiField CommitBox commit; @UiField RelatedChanges related; @UiField FileTable files; @UiField FlowPanel history; + @UiField Button revisions; @UiField Button download; @UiField Button reply; @UiField Button expandAll; @@ -155,6 +149,7 @@ public class ChangeScreen2 extends Screen { @UiField QuickApprove quickApprove; private ReplyAction replyAction; private EditMessageAction editMessageAction; + private RevisionsAction revisionsAction; private DownloadAction downloadAction; public ChangeScreen2(Change.Id changeId, String revision, boolean openReplyBox) { @@ -179,8 +174,10 @@ public class ChangeScreen2 extends Screen { void loadChangeInfo(boolean fg, AsyncCallback cb) { RestApi call = ChangeApi.detail(changeId.get()); ChangeList.addOptions(call, EnumSet.of( - ListChangesOption.ALL_REVISIONS, - ListChangesOption.CURRENT_ACTIONS)); + ListChangesOption.CURRENT_ACTIONS, + fg && revision != null + ? ListChangesOption.ALL_REVISIONS + : ListChangesOption.CURRENT_REVISION)); if (!fg) { call.background(); } @@ -247,7 +244,13 @@ public class ChangeScreen2 extends Screen { } } - private void renderDownload(ChangeInfo info, String revision) { + private void initRevisionsAction(ChangeInfo info, String revision) { + revisionsAction = new RevisionsAction( + info.legacy_id(), revision, + style, headerLine, revisions); + } + + private void initDownloadAction(ChangeInfo info, String revision) { downloadAction = new DownloadAction( info.legacy_id(), info.project(), @@ -341,14 +344,9 @@ public class ChangeScreen2 extends Screen { downloadAction.show(); } - @UiHandler("revisionList") - void onChangeRevision(ChangeEvent e) { - int idx = revisionList.getSelectedIndex(); - if (0 <= idx) { - String n = revisionList.getValue(idx); - revisionList.setEnabled(false); - Gerrit.display(PageLinks.toChange2(changeId, n)); - } + @UiHandler("revisions") + void onRevision(ClickEvent e) { + revisionsAction.show(); } @UiHandler("reply") @@ -597,9 +595,9 @@ public class ChangeScreen2 extends Screen { renderOwner(info); renderReviewers(info); renderActionTextDate(info); - renderDownload(info, revision); - renderRevisions(info); renderHistory(info); + initRevisionsAction(info, revision); + initDownloadAction(info, revision); actions.display(info, revision); star.setValue(info.starred()); @@ -660,35 +658,6 @@ public class ChangeScreen2 extends Screen { ccText.setInnerSafeHtml(labels.formatUserList(cc.values())); } - private void renderRevisions(ChangeInfo info) { - if (info.revisions().size() == 1) { - UIObject.setVisible(revisionParent, false); - return; - } - - JsArray list = info.revisions().values(); - RevisionInfo.sortRevisionInfoByNumber(list); - if (Gerrit.isSignedIn() - && Gerrit.getUserAccount().getGeneralPreferences() - .isReversePatchSetOrder()) { - Collections.reverse(Natives.asList(list)); - } - - int selected = -1; - for (int i = 0; i < list.length(); i++) { - RevisionInfo r = list.get(i); - revisionList.addItem( - r._number() + ": " + r.name().substring(0, 6), - "" + r._number()); - if (revision.equals(r.name())) { - selected = i; - } - } - if (0 <= selected) { - revisionList.setSelectedIndex(selected); - } - } - private void renderOwner(ChangeInfo info) { // TODO info card hover ownerText.setInnerText(info.owner().name() != null 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 8e4b8f4d07..b24b311f9e 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 @@ -97,6 +97,7 @@ limitations under the License. margin: 0; padding-left: 2px; padding-right: 2px; + min-width: 100px; } .popdown button div { padding-left: 6px; @@ -256,14 +257,14 @@ limitations under the License. -
-
- Revision -
+ + +
Revisions
+
Download
-
+ diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.java index ce2fe7b075..ff00e92c3a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.java @@ -19,4 +19,9 @@ interface Constants extends com.google.gwt.i18n.client.Constants { String nextChange(); String openChange(); String reviewedFileTitle(); + + String ps(); + String commit(); + String date(); + String author(); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.properties index 95f378cc7e..bb9450febb 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Constants.properties @@ -2,3 +2,8 @@ previousChange = Previous related change nextChange = Next related change openChange = Open related change reviewedFileTitle = Mark file as reviewed (Shortcut: r) + +ps = PS +commit = Commit +date = Date +author = Author diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsAction.java new file mode 100644 index 0000000000..d66127b28f --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsAction.java @@ -0,0 +1,37 @@ +// 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.user.client.ui.UIObject; +import com.google.gwt.user.client.ui.Widget; + +class RevisionsAction extends RightSidePopdownAction { + private final RevisionsBox revisionBox; + + RevisionsAction( + Change.Id changeId, + String revision, + ChangeScreen2.Style style, + UIObject relativeTo, + Widget downloadButton) { + super(style, relativeTo, downloadButton); + this.revisionBox = new RevisionsBox(changeId, revision); + } + + Widget getWidget() { + return revisionBox; + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.java new file mode 100644 index 0000000000..c0b2112844 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.java @@ -0,0 +1,219 @@ +// 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.FormatUtil; +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.changes.ChangeApi; +import com.google.gerrit.client.changes.ChangeInfo; +import com.google.gerrit.client.changes.ChangeInfo.CommitInfo; +import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo; +import com.google.gerrit.client.changes.ChangeList; +import com.google.gerrit.client.rpc.NativeMap; +import com.google.gerrit.client.rpc.Natives; +import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.client.ui.FancyFlexTableImpl; +import com.google.gerrit.common.PageLinks; +import com.google.gerrit.common.changes.ListChangesOption; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.JsArray; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlexTable; +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.gwt.user.client.ui.impl.HyperlinkImpl; +import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; + +import java.util.Collections; +import java.util.EnumSet; + +class RevisionsBox extends Composite { + interface Binder extends UiBinder {} + private static final Binder uiBinder = GWT.create(Binder.class); + + private static final String OPEN; + private static final HyperlinkImpl link = GWT.create(HyperlinkImpl.class); + + static { + OPEN = DOM.createUniqueId().replace('-', '_'); + init(OPEN); + } + + private static final native void init(String o) /*-{ + $wnd[o] = $entry(function(e,i) { + return @com.google.gerrit.client.change.RevisionsBox::onOpen(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i); + }); + }-*/; + + private static boolean onOpen(NativeEvent e, int idx) { + if (link.handleAsClick(e. cast())) { + RevisionsBox t = getRevisionBox(e); + if (t != null) { + t.onOpenRow(idx); + e.preventDefault(); + return false; + } + } + return true; + } + + private static RevisionsBox getRevisionBox(NativeEvent event) { + com.google.gwt.user.client.Element e = event.getEventTarget().cast(); + for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) { + EventListener l = DOM.getEventListener(e); + if (l instanceof RevisionsBox) { + return (RevisionsBox) l; + } + } + return null; + } + + interface Style extends CssResource { + String current(); + String legacy_id(); + String commit(); + } + + private final Change.Id changeId; + private final String revision; + private boolean loaded; + private JsArray revisions; + + @UiField FlexTable table; + @UiField Style style; + + RevisionsBox(Change.Id changeId, String revision) { + this.changeId = changeId; + this.revision = revision; + initWidget(uiBinder.createAndBindUi(this)); + } + + @Override + protected void onLoad() { + if (!loaded) { + RestApi call = ChangeApi.detail(changeId.get()); + ChangeList.addOptions(call, EnumSet.of( + ListChangesOption.ALL_REVISIONS, + ListChangesOption.ALL_COMMITS)); + call.get(new AsyncCallback() { + @Override + public void onSuccess(ChangeInfo result) { + render(result.revisions()); + loaded = true; + } + + @Override + public void onFailure(Throwable caught) { + } + }); + } + } + + private void onOpenRow(int idx) { + closeParent(); + Gerrit.display(url(revisions.get(idx))); + } + + private void render(NativeMap map) { + map.copyKeysIntoChildren("name"); + + revisions = map.values(); + RevisionInfo.sortRevisionInfoByNumber(revisions); + Collections.reverse(Natives.asList(revisions)); + + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + header(sb); + for (int i = 0; i < revisions.length(); i++) { + revision(sb, i, revisions.get(i)); + } + + GWT. create(FancyFlexTableImpl.class) + .resetHtml(table, sb); + } + + private void header(SafeHtmlBuilder sb) { + sb.openTr() + .openTh() + .setStyleName(style.legacy_id()) + .append(Resources.C.ps()) + .closeTh() + .openTh().append(Resources.C.commit()).closeTh() + .openTh().append(Resources.C.date()).closeTh() + .openTh().append(Resources.C.author()).closeTh() + .closeTr(); + } + + private void revision(SafeHtmlBuilder sb, int index, RevisionInfo r) { + CommitInfo c = r.commit(); + sb.openTr(); + if (revision.equals(r.name())) { + sb.setStyleName(style.current()); + } + + sb.openTd() + .setStyleName(style.legacy_id()) + .append(r._number()) + .closeTd(); + + sb.openTd() + .setStyleName(style.commit()) + .openAnchor() + .setAttribute("href", "#" + url(r)) + .setAttribute("onclick", OPEN + "(event," + index + ")") + .append(r.name().substring(0, 10)) + .closeAnchor() + .closeTd(); + + sb.openTd() + .append(FormatUtil.shortFormatDayTime(c.committer().date())) + .closeTd(); + + String an = c.author() != null ? c.author().name() : null; + String cn = c.committer() != null ? c.committer().name() : null; + sb.openTd(); + sb.append(an); + if (!"".equals(an) && !"".equals(cn) && !an.equals(cn)) { + sb.append(" / ").append(cn); + } + sb.closeTd(); + + sb.closeTr(); + } + + private String url(RevisionInfo r) { + return PageLinks.toChange2( + changeId, + String.valueOf(r._number())); + } + + private void closeParent() { + for (Widget w = getParent(); w != null; w = w.getParent()) { + if (w instanceof PopupPanel) { + ((PopupPanel) w).hide(true); + break; + } + } + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.ui.xml new file mode 100644 index 0000000000..bf1ddd43b3 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevisionsBox.ui.xml @@ -0,0 +1,65 @@ + + + + + + @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor; + + .revisionBox { + min-width: 300px; + margin: 10px 0px 5px 5px; + } + + .scroll { + min-width: 300px; + height: 200px; + } + + .table { + border-spacing: 0; + width: 100%; + } + + .table td, .table th { + padding-left: 5px; + padding-right: 5px; + border-right: 2px solid #ddd; + white-space: nowrap; + } + + .table tr.current { + background-color: selectionColor; + } + + .legacy_id { + min-width: 50px; + text-align: right; + font-weight: bold; + } + + .commit { + font-family: monospace; + } + + + + + + + diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java index 2c7451a54d..2836e0f131 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImpl.java @@ -14,13 +14,13 @@ package com.google.gerrit.client.ui; -import com.google.gerrit.client.ui.FancyFlexTable.MyFlexTable; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HTMLTable; import com.google.gwtexpui.safehtml.client.SafeHtml; public class FancyFlexTableImpl { - public void resetHtml(final MyFlexTable myTable, final SafeHtml body) { + public void resetHtml(final FlexTable myTable, final SafeHtml body) { SafeHtml.setInnerHTML(getBodyElement(myTable), body); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE6.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE6.java index 17e8ddd723..34b6bee046 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE6.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTableImplIE6.java @@ -14,16 +14,16 @@ package com.google.gerrit.client.ui; -import com.google.gerrit.client.ui.FancyFlexTable.MyFlexTable; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HTMLTable; import com.google.gwtexpui.safehtml.client.SafeHtml; import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; public class FancyFlexTableImplIE6 extends FancyFlexTableImpl { @Override - public void resetHtml(final MyFlexTable myTable, final SafeHtml bodyHtml) { + public void resetHtml(final FlexTable myTable, final SafeHtml bodyHtml) { final Element oldBody = getBodyElement(myTable); final Element newBody = parseBody(bodyHtml); assert newBody != null;