Add icons to switch between side-by-side and unified diff view

For change edits the icon is not displayed, because the unified diff
view is not able to handle change edits yet.

Change-Id: I02b9800d40a510b9f90d6890e619aec89c8933d5
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java
index 0c728ae..b1312db 100644
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java
+++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/Resources.java
@@ -101,4 +101,10 @@
 
   @Source("goUp.png")
   public ImageResource goUp();
+
+  @Source("sideBySideDiff.png")
+  public ImageResource sideBySideDiff();
+
+  @Source("unifiedDiff.png")
+  public ImageResource unifiedDiff();
 }
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png
new file mode 100755
index 0000000..ee70080
--- /dev/null
+++ b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/sideBySideDiff.png
Binary files differ
diff --git a/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png
new file mode 100755
index 0000000..ec5f97a
--- /dev/null
+++ b/gerrit-gwtui-common/src/main/resources/com/google/gerrit/client/unifiedDiff.png
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
index 3772b01..f7ae24a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java
@@ -47,6 +47,7 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.HTMLPanel;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.UIObject;
@@ -55,6 +56,8 @@
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
+import java.util.List;
+
 class Header extends Composite {
   interface Binder extends UiBinder<HTMLPanel, Header> {}
   private static final Binder uiBinder = GWT.create(Binder.class);
@@ -71,6 +74,7 @@
   @UiField Element filePath;
 
   @UiField Element noDiff;
+  @UiField FlowPanel linkPanel;
 
   @UiField InlineHyperlink prev;
   @UiField InlineHyperlink up;
@@ -207,9 +211,13 @@
     project.setInnerText(info.project());
   }
 
-  void init(PreferencesAction pa) {
+  void init(PreferencesAction pa, List<InlineHyperlink> links) {
     prefsAction = pa;
     prefsAction.setPartner(preferences);
+
+    for (InlineHyperlink link : links) {
+      linkPanel.add(link);
+    }
   }
 
   @UiHandler("reviewed")
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
index 08b64db..c58eef7 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.ui.xml
@@ -47,6 +47,13 @@
     vertical-align: top;
     font-weight: bold;
     margin-right: 1em;
+    float: left;
+  }
+  .linkPanel {
+    float: left;
+  }
+  .linkPanel img {
+    padding-right: 3px;
   }
   .preferences {
     cursor: pointer;
@@ -61,6 +68,7 @@
     <span class='{style.path}'><span ui:field='project'/> / <span ui:field='filePath'/></span>
     <div class='{style.navigation}'>
       <span ui:field='noDiff' class='{style.nodiff}'><ui:msg>No Differences</ui:msg></span>
+      <g:FlowPanel ui:field='linkPanel' styleName='{style.linkPanel}'/>
       <x:InlineHyperlink ui:field='prev' styleName='{res.style.goPrev}'/>
       <x:InlineHyperlink ui:field='up'
           styleName='{res.style.goUp}'
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
index fcfdf13..e86801f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide2.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.RestApi;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
+import com.google.gerrit.client.ui.InlineHyperlink;
 import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.extensions.common.ListChangesOption;
@@ -61,6 +62,7 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.ImageResourceRenderer;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
@@ -77,6 +79,7 @@
 import net.codemirror.lib.ModeInjector;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 
@@ -614,7 +617,7 @@
             chunkManager.getLineMapper());
 
     prefsAction = new PreferencesAction(this, prefs);
-    header.init(prefsAction);
+    header.init(prefsAction, getLinks());
 
     if (prefs.syntaxHighlighting() && fileSize.compareTo(FileSize.SMALL) > 0) {
       Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
@@ -629,6 +632,35 @@
     }
   }
 
+  private List<InlineHyperlink> getLinks() {
+    // skip change edits
+    if (revision.get() > 0) {
+      InlineHyperlink toUnifiedDiffLink = new InlineHyperlink();
+      toUnifiedDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
+      toUnifiedDiffLink.setTargetHistoryToken(getUnifiedDiffUrl());
+      toUnifiedDiffLink.setTitle(PatchUtil.C.unifiedDiff());
+      return Collections.singletonList(toUnifiedDiffLink);
+    } else {
+      return Collections.emptyList();
+    }
+  }
+
+  private String getUnifiedDiffUrl() {
+    StringBuilder url = new StringBuilder();
+    url.append("/c/");
+    url.append(changeId.get());
+    url.append("/");
+    if (base != null) {
+      url.append(base.get());
+      url.append("..");
+    }
+    url.append(revision.get());
+    url.append("/");
+    url.append(path);
+    url.append(",unified");
+    return url.toString();
+  }
+
   private CodeMirror newCM(
       DiffInfo.FileMeta meta,
       String contents,
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
index 9f36342..907a7f6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
@@ -29,10 +30,12 @@
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 
+import java.util.List;
+
 class NavLinks extends Composite {
   public enum Nav {
     PREV (0, '[', PatchUtil.C.previousFileHelp(), 0),
-    NEXT (2, ']', PatchUtil.C.nextFileHelp(), 1);
+    NEXT (3, ']', PatchUtil.C.nextFileHelp(), 1);
 
     public int col;      // Table Cell column to display link in
     public int key;      // key code shortcut to activate link
@@ -56,7 +59,7 @@
   NavLinks(KeyCommandSet kcs, PatchSet.Id forPatch) {
     patchSetId = forPatch;
     keys = kcs;
-    table = new Grid(1, 3);
+    table = new Grid(1, 4);
     initWidget(table);
 
     final CellFormatter fmt = table.getCellFormatter();
@@ -64,13 +67,15 @@
     fmt.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT);
     fmt.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
     fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);
+    fmt.setHorizontalAlignment(0, 3, HasHorizontalAlignment.ALIGN_RIGHT);
 
     final ChangeLink up = new ChangeLink("", patchSetId);
     SafeHtml.set(up, SafeHtml.asis(Util.C.upToChangeIconLink()));
     table.setWidget(0, 1, up);
   }
 
-  void display(int patchIndex, PatchScreen.Type type, PatchTable fileList) {
+  void display(int patchIndex, PatchScreen.Type type, PatchTable fileList,
+      List<InlineHyperlink> links) {
     if (fileList != null) {
       setupNav(Nav.PREV, fileList.getPreviousPatchLink(patchIndex, type));
       setupNav(Nav.NEXT, fileList.getNextPatchLink(patchIndex, type));
@@ -78,6 +83,11 @@
       setupNav(Nav.PREV, null);
       setupNav(Nav.NEXT, null);
     }
+    FlowPanel linkPanel = new FlowPanel();
+    for (InlineHyperlink link : links) {
+      linkPanel.add(link);
+    }
+    table.setWidget(0, 2, linkPanel);
   }
 
   protected void setupNav(final Nav nav, final InlineHyperlink link) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
index 82d664d..0a99a98 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
@@ -89,4 +89,7 @@
 
   String patchSkipRegionStart();
   String patchSkipRegionEnd();
+
+  String sideBySideDiff();
+  String unifiedDiff();
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
index 84ae02c..0a9ce83 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
@@ -68,3 +68,6 @@
 
 patchSkipRegionStart = ... skipped
 patchSkipRegionEnd = common lines ...
+
+sideBySideDiff = side-by-side diff
+unifiedDiff = unified diff
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index 1024a98..67db7d1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.CommentLinkProcessor;
+import com.google.gerrit.client.ui.InlineHyperlink;
 import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
 import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.data.PatchScript;
@@ -43,10 +44,14 @@
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.ImageResourceRenderer;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
 
+import java.util.Collections;
+import java.util.List;
+
 public abstract class PatchScreen extends Screen implements
     CommentEditorContainer {
   static final PrettyFactory PRETTY = ClientSideFormatter.FACTORY;
@@ -271,11 +276,49 @@
     }
 
     if (fileList != null) {
-      topNav.display(patchIndex, getPatchScreenType(), fileList);
-      bottomNav.display(patchIndex, getPatchScreenType(), fileList);
+      topNav.display(patchIndex, getPatchScreenType(), fileList, getLinks());
+      bottomNav.display(patchIndex, getPatchScreenType(), fileList, getLinks());
     }
   }
 
+  private List<InlineHyperlink> getLinks() {
+    if (contentTable instanceof SideBySideTable) {
+      InlineHyperlink toUnifiedDiffLink = new InlineHyperlink();
+      toUnifiedDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
+      toUnifiedDiffLink.setTargetHistoryToken(getUnifiedDiffUrl());
+      toUnifiedDiffLink.setTitle(PatchUtil.C.unifiedDiff());
+      return Collections.singletonList(toUnifiedDiffLink);
+    } else if (contentTable instanceof UnifiedDiffTable) {
+      InlineHyperlink toSideBySideDiffLink = new InlineHyperlink();
+      toSideBySideDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff()));
+      toSideBySideDiffLink.setTargetHistoryToken(getSideBySideDiffUrl());
+      toSideBySideDiffLink.setTitle(PatchUtil.C.sideBySideDiff());
+      return Collections.singletonList(toSideBySideDiffLink);
+    } else {
+      throw new IllegalStateException("unknown table type: "
+          + contentTable.getClass().getSimpleName());
+    }
+  }
+
+  private String getSideBySideDiffUrl() {
+    StringBuilder url = new StringBuilder();
+    url.append("/c/");
+    url.append(patchKey.getParentKey().getParentKey().get());
+    url.append("/");
+    if (idSideA != null) {
+      url.append(idSideA.get());
+      url.append("..");
+    }
+    url.append(idSideB.get());
+    url.append("/");
+    url.append(patchKey.getFileName());
+    return url.toString();
+  }
+
+  private String getUnifiedDiffUrl() {
+    return getSideBySideDiffUrl() + ",unified";
+  }
+
   @Override
   protected void onLoad() {
     super.onLoad();
@@ -485,8 +528,8 @@
     lastScript = script;
 
     if (fileList != null) {
-      topNav.display(patchIndex, getPatchScreenType(), fileList);
-      bottomNav.display(patchIndex, getPatchScreenType(), fileList);
+      topNav.display(patchIndex, getPatchScreenType(), fileList, getLinks());
+      bottomNav.display(patchIndex, getPatchScreenType(), fileList, getLinks());
     }
 
     if (Gerrit.isSignedIn()) {