Make branch columns link to changes on that branch

Similar to what we do with the project column, link the branch name
in the branch column to all changes that match that branch, and the
topic field to changes matching the topic.

Bug: issue 509
Change-Id: I9f7c4702c3dde1704ea5a935fcbea3e478108179
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
index a1c1b6b..0c7106e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
@@ -18,6 +18,7 @@
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.ui.AccountDashboardLink;
+import com.google.gerrit.client.ui.BranchLink;
 import com.google.gerrit.client.ui.ChangeLink;
 import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gerrit.common.data.AccountInfoCache;
@@ -83,8 +84,10 @@
 
     table.setWidget(R_OWNER, 1, AccountDashboardLink.link(acc, chg.getOwner()));
     table.setWidget(R_PROJECT, 1, new ProjectLink(chg.getProject(), chg.getStatus()));
-    table.setText(R_BRANCH, 1, dst.getShortName());
-    table.setText(R_TOPIC, 1, chg.getTopic());
+    table.setWidget(R_BRANCH, 1, new BranchLink(dst.getShortName(), chg
+        .getProject(), chg.getStatus(), dst.get(), null));
+    table.setWidget(R_TOPIC, 1, new BranchLink(chg.getTopic(),
+        chg.getProject(), chg.getStatus(), dst.get(), chg.getTopic()));
     table.setText(R_UPLOADED, 1, mediumFormat(chg.getCreatedOn()));
     table.setText(R_UPDATED, 1, mediumFormat(chg.getLastUpdatedOn()));
     table.setText(R_STATUS, 1, Util.toLongString(chg.getStatus()));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 5ede95f..76b9f49 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.client.patches.PatchUtil;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.AccountDashboardLink;
+import com.google.gerrit.client.ui.BranchLink;
 import com.google.gerrit.client.ui.ChangeLink;
 import com.google.gerrit.client.ui.NavigationTable;
 import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
@@ -226,12 +227,8 @@
     table.setWidget(row, C_OWNER, link(c.getOwner()));
     table.setWidget(row, C_PROJECT, new ProjectLink(c.getProject().getKey(), c
         .getStatus()));
-
-    String branchText = c.getBranch();
-    if (c.getTopic() != null) {
-      branchText += " (" + c.getTopic() + ")";
-    }
-    table.setText(row, C_BRANCH, branchText);
+    table.setWidget(row, C_BRANCH, new BranchLink(c.getProject().getKey(), c
+        .getStatus(), c.getBranch(), c.getTopic()));
     table.setText(row, C_LAST_UPDATE, shortFormat(c.getLastUpdatedOn()));
     setRowItem(row, c);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
new file mode 100644
index 0000000..01d7d8b
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
@@ -0,0 +1,84 @@
+// Copyright (C) 2009 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.ui;
+
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.changes.QueryScreen;
+import com.google.gerrit.common.PageLinks;
+import com.google.gerrit.reviewdb.Branch;
+import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.Project;
+
+/** Link to the open changes of a project. */
+public class BranchLink extends InlineHyperlink {
+  private final String query;
+
+  public BranchLink(Project.NameKey project, Change.Status status,
+      String branch, String topic) {
+    this(text(branch, topic), query(project, status, branch, topic));
+  }
+
+  public BranchLink(String text, Project.NameKey project, Change.Status status,
+      String branch, String topic) {
+    this(text, query(project, status, branch, topic));
+  }
+
+  private BranchLink(String text, String query) {
+    super(text, PageLinks.toChangeQuery(query));
+    this.query = query;
+  }
+
+  @Override
+  public void go() {
+    Gerrit.display(getTargetHistoryToken(), createScreen());
+  }
+
+  private Screen createScreen() {
+    return QueryScreen.forQuery(query);
+  }
+
+  private static String text(String branch, String topic) {
+    if (topic != null && !topic.isEmpty()) {
+      return branch + " (" + topic + ")";
+    } else {
+      return branch;
+    }
+  }
+
+  private static String query(Project.NameKey project, Change.Status status,
+      String branch, String topic) {
+    String query = PageLinks.projectQuery(project, status);
+
+    if (branch.startsWith(Branch.R_REFS)) {
+      if (branch.startsWith(Branch.R_HEADS)) {
+        query += " " + PageLinks.op("branch", //
+            branch.substring(Branch.R_HEADS.length()));
+      } else {
+        query += " " + PageLinks.op("ref", branch);
+      }
+    } else {
+      // Assume it was clipped already by the caller.  This
+      // happens for example inside of the ChangeInfo object.
+      //
+      query += " " + PageLinks.op("branch", branch);
+    }
+
+    if (topic != null && !topic.isEmpty()) {
+      query += " " + PageLinks.op("topic", topic);
+    }
+
+    return query;
+  }
+}