Merge "ChangeScreen2: Show "Included in" information for merged changes"
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 155881a..2f9a670 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
@@ -47,6 +47,7 @@
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Change.Status;
 import com.google.gerrit.reviewdb.client.Project.SubmitType;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JsArray;
@@ -150,6 +151,7 @@
   @UiField FileTable files;
   @UiField FlowPanel history;
 
+  @UiField Button includedIn;
   @UiField Button revisions;
   @UiField Button download;
   @UiField Button reply;
@@ -159,6 +161,7 @@
   @UiField QuickApprove quickApprove;
   private ReplyAction replyAction;
   private EditMessageAction editMessageAction;
+  private IncludedInAction includedInAction;
   private RevisionsAction revisionsAction;
   private DownloadAction downloadAction;
 
@@ -265,6 +268,15 @@
     }
   }
 
+  private void initIncludedInAction(ChangeInfo info) {
+    if (info.status() == Status.MERGED) {
+      includedInAction = new IncludedInAction(
+          info.legacy_id(),
+          style, headerLine, includedIn);
+      includedIn.setVisible(true);
+    }
+  }
+
   private void initRevisionsAction(ChangeInfo info, String revision) {
     revisionsAction = new RevisionsAction(
         info.legacy_id(), revision,
@@ -360,6 +372,11 @@
     StarredChanges.toggleStar(changeId, e.getValue());
   }
 
+  @UiHandler("includedIn")
+  void onIncludedIn(ClickEvent e) {
+    includedInAction.show();
+  }
+
   @UiHandler("download")
   void onDownload(ClickEvent e) {
     downloadAction.show();
@@ -616,6 +633,7 @@
     renderOwner(info);
     renderActionTextDate(info);
     renderHistory(info);
+    initIncludedInAction(info);
     initRevisionsAction(info, revision);
     initDownloadAction(info, revision);
     actions.display(info, revision);
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 147f786..f2b0cb0 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
@@ -287,6 +287,9 @@
       </div>
 
       <g:FlowPanel styleName='{style.popdown}'>
+        <g:Button ui:field='includedIn' styleName='' visible="false">
+          <div><ui:msg>Included in</ui:msg></div>
+        </g:Button>
         <g:Button ui:field='revisions' styleName=''>
           <div><ui:msg>Revisions</ui:msg></div>
         </g:Button>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java
new file mode 100644
index 0000000..58b286c
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java
@@ -0,0 +1,36 @@
+// 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 IncludedInAction extends RightSidePopdownAction {
+  private final IncludedInBox includedInBox;
+
+  IncludedInAction(
+      Change.Id changeId,
+      ChangeScreen2.Style style,
+      UIObject relativeTo,
+      Widget includedInButton) {
+    super(style, relativeTo, includedInButton);
+    this.includedInBox = new IncludedInBox(changeId);
+  }
+
+  Widget getWidget() {
+    return includedInBox;
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java
new file mode 100644
index 0000000..927e500
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java
@@ -0,0 +1,85 @@
+// 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.changes.ChangeApi;
+import com.google.gerrit.client.changes.ChangeInfo.IncludedInInfo;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
+
+class IncludedInBox extends Composite {
+  interface Binder extends UiBinder<HTMLPanel, IncludedInBox> {}
+  private static final Binder uiBinder = GWT.create(Binder.class);
+
+  interface Style extends CssResource {
+    String includedInElement();
+  }
+
+  private final Change.Id changeId;
+  private boolean loaded;
+
+  @UiField Style style;
+  @UiField Element branches;
+  @UiField Element tags;
+
+  IncludedInBox(Change.Id changeId) {
+    this.changeId = changeId;
+    initWidget(uiBinder.createAndBindUi(this));
+  }
+
+  @Override
+  protected void onLoad() {
+    if (!loaded) {
+      ChangeApi.includedIn(changeId.get(),
+          new AsyncCallback<IncludedInInfo>() {
+        @Override
+        public void onSuccess(IncludedInInfo r) {
+          branches.setInnerSafeHtml(formatList(r.branches()));
+          tags.setInnerSafeHtml(formatList(r.tags()));
+          loaded = true;
+        }
+
+        @Override
+        public void onFailure(Throwable caught) {
+        }
+      });
+    }
+  }
+
+  private SafeHtml formatList(JsArrayString l) {
+    SafeHtmlBuilder html = new SafeHtmlBuilder();
+    int size = l.length();
+    for (int i = 0; i < size; i++) {
+      html.openSpan()
+          .addStyleName(style.includedInElement())
+          .append(l.get(i))
+          .closeSpan();
+      if (i < size - 1) {
+        html.append(", ");
+      }
+    }
+    return html;
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml
new file mode 100644
index 0000000..59b05f0
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.ui.xml
@@ -0,0 +1,77 @@
+<?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'>
+  <ui:style type='com.google.gerrit.client.change.IncludedInBox.Style'>
+    .includedInBox {
+      min-width: 300px;
+      max-width: 580px;
+      margin: 5px;
+    }
+
+    .includedInTable {
+      border-spacing: 0;
+    }
+
+    .includedInTable th {
+      width: 60px;
+      color: #444;
+      font-weight: normal;
+      vertical-align: top;
+      text-align: left;
+      padding-right: 5px;
+    }
+
+    .includedInElement {
+      font-size: smaller;
+      font-family: monospace;
+    }
+
+    .includedInElement span {
+      width: 500px;
+      white-space: nowrap;
+      display: inline-block;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
+    .includedInElement .gwt-TextBox {
+      padding: 0;
+      margin: 0;
+      border: 0;
+      max-height: 18px;
+      width: 500px;
+    }
+
+    .includedInElement div {
+      float: right;
+    }
+  </ui:style>
+  <g:HTMLPanel styleName='{style.includedInBox}'>
+    <table class='{style.includedInTable}'>
+      <tr>
+        <th><ui:msg>Branches</ui:msg></th>
+          <td ui:field='branches'/>
+      </tr>
+      <tr>
+        <th><ui:msg>Tags</ui:msg></th>
+          <td ui:field='tags'/>
+      </tr>
+    </table>
+  </g:HTMLPanel>
+</ui:UiBinder>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
index fb88e92..97b0166 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.client.changes;
 
+import com.google.gerrit.client.changes.ChangeInfo.IncludedInInfo;
 import com.google.gerrit.client.rpc.NativeString;
 import com.google.gerrit.client.rpc.RestApi;
 import com.google.gerrit.reviewdb.client.PatchSet;
@@ -69,6 +70,10 @@
     return call(id, "detail");
   }
 
+  public static void includedIn(int id, AsyncCallback<IncludedInInfo> cb) {
+    call(id, "in").get(cb);
+  }
+
   public static RestApi revision(int id, String revision) {
     return change(id).view("revisions").id(revision);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
index dac4660..d46b7ca 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
@@ -282,4 +282,12 @@
     protected MergeableInfo() {
     }
   }
+
+  public static class IncludedInInfo extends JavaScriptObject {
+    public final native JsArrayString branches() /*-{ return this.branches; }-*/;
+    public final native JsArrayString tags() /*-{ return this.tags; }-*/;
+
+    protected IncludedInInfo() {
+    }
+  }
 }