| // 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.ChangeList; |
| import com.google.gerrit.client.info.ChangeInfo; |
| import com.google.gerrit.client.info.ChangeInfo.CommitInfo; |
| import com.google.gerrit.client.info.ChangeInfo.EditInfo; |
| import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; |
| 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.extensions.client.ListChangesOption; |
| import com.google.gerrit.reviewdb.client.Change; |
| import com.google.gerrit.reviewdb.client.Project; |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.core.client.JsArray; |
| import com.google.gwt.dom.client.Element; |
| 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 PatchSetsBox extends Composite { |
| interface Binder extends UiBinder<HTMLPanel, PatchSetsBox> {} |
| |
| 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 native void init(String o) /*-{ |
| $wnd[o] = $entry(function(e,i) { |
| return @com.google.gerrit.client.change.PatchSetsBox::onOpen(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i); |
| }); |
| }-*/; |
| |
| private static boolean onOpen(NativeEvent e, int idx) { |
| if (link.handleAsClick(e.<Event>cast())) { |
| PatchSetsBox t = getRevisionBox(e); |
| if (t != null) { |
| t.onOpenRow(idx); |
| e.preventDefault(); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private static PatchSetsBox getRevisionBox(NativeEvent event) { |
| Element e = event.getEventTarget().cast(); |
| for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) { |
| EventListener l = DOM.getEventListener(e); |
| if (l instanceof PatchSetsBox) { |
| return (PatchSetsBox) l; |
| } |
| } |
| return null; |
| } |
| |
| interface Style extends CssResource { |
| String current(); |
| |
| String legacy_id(); |
| |
| String commit(); |
| |
| String draft_comment(); |
| } |
| |
| private final Change.Id changeId; |
| private final Project.NameKey project; |
| private final String revision; |
| private final EditInfo edit; |
| private boolean loaded; |
| private JsArray<RevisionInfo> revisions; |
| |
| @UiField FlexTable table; |
| @UiField Style style; |
| |
| PatchSetsBox(Project.NameKey project, Change.Id changeId, String revision, EditInfo edit) { |
| this.project = project; |
| this.changeId = changeId; |
| this.revision = revision; |
| this.edit = edit; |
| initWidget(uiBinder.createAndBindUi(this)); |
| } |
| |
| @Override |
| protected void onLoad() { |
| if (!loaded) { |
| RestApi call = ChangeApi.detail(project.get(), changeId.get()); |
| ChangeList.addOptions( |
| call, EnumSet.of(ListChangesOption.ALL_COMMITS, ListChangesOption.ALL_REVISIONS)); |
| call.get( |
| new AsyncCallback<ChangeInfo>() { |
| @Override |
| public void onSuccess(ChangeInfo result) { |
| if (edit != null) { |
| edit.setName(edit.commit().commit()); |
| result.revisions().put(edit.name(), RevisionInfo.fromEdit(edit)); |
| } |
| 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<RevisionInfo> 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.<FancyFlexTableImpl>create(FancyFlexTableImpl.class).resetHtml(table, sb); |
| } |
| |
| private void header(SafeHtmlBuilder sb) { |
| sb.openTr() |
| .openTh() |
| .setStyleName(style.legacy_id()) |
| .append(Resources.C.patchSet()) |
| .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()); |
| sb.append(r.id()); |
| sb.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() : ""; |
| String cn = c.committer() != null ? c.committer().name() : ""; |
| 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.toChange(project, changeId, r.id()); |
| } |
| |
| private void closeParent() { |
| for (Widget w = getParent(); w != null; w = w.getParent()) { |
| if (w instanceof PopupPanel) { |
| ((PopupPanel) w).hide(true); |
| break; |
| } |
| } |
| } |
| } |