Make gr-builder a Polymer component

Change-Id: I0d99775332b0ef473459ad481970ad6033427c7d
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-image.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-image.js
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-side-by-side.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-side-by-side.js
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-unified.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder-unified.js
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
new file mode 100644
index 0000000..76cb844
--- /dev/null
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
@@ -0,0 +1,127 @@
+<!--
+Copyright (C) 2016 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.
+-->
+<link rel="import" href="../../../bower_components/polymer/polymer.html">
+
+<dom-module id="gr-diff-builder">
+  <template>
+    <div class="contentWrapper">
+      <content></content>
+    </div>
+  </template>
+  <script src="../gr-diff/gr-diff-line.js"></script>
+  <script src="../gr-diff/gr-diff-group.js"></script>
+  <script src="gr-diff-builder.js"></script>
+  <script src="gr-diff-builder-side-by-side.js"></script>
+  <script src="gr-diff-builder-unified.js"></script>
+  <script src="gr-diff-builder-image.js"></script>
+  <script>
+    (function() {
+      'use strict';
+
+      var DiffViewMode = {
+        SIDE_BY_SIDE: 'SIDE_BY_SIDE',
+        UNIFIED: 'UNIFIED_DIFF',
+      };
+
+      Polymer({
+        is: 'gr-diff-builder',
+
+        /**
+         * Fired when the diff is rendered.
+         *
+         * @event render
+         */
+
+        properties: {
+          viewMode: String,
+          isImageDiff: Boolean,
+          baseImage: Object,
+          revisionImage: Object,
+          _builder: Object,
+        },
+
+        render: function(diff, comments, prefs) {
+          this._builder = this._getDiffBuilder(diff, comments, prefs);
+          this._renderDiff();
+        },
+
+        createCommentThread: function(changeNum, patchNum, path, side,
+            projectConfig) {
+          this._builder.createCommentThread(changeNum, patchNum, path, side,
+            projectConfig);
+        },
+
+        getGroups: function() {
+          return this._builder._groups;
+        },
+
+        emitGroup: function(group, sectionEl) {
+          this._builder.emitGroup(group, sectionEl);
+        },
+
+        emitDiff: function() {
+          this._builder.emitDiff();
+        },
+
+        showContext: function(group, sectionEl) {
+          var groups = this._builder._groups;
+          // TODO(viktard): Polyfill findIndex for IE10.
+          var contextIndex = groups.findIndex(function(group) {
+            return group.element == sectionEl;
+          });
+          groups.splice.apply(groups, [contextIndex, 1].concat(newGroups));
+
+          newGroups.forEach(function(newGroup) {
+            this._builder.emitGroup(newGroup, sectionEl);
+          }.bind(this));
+          sectionEl.parentNode.removeChild(sectionEl);
+
+          this.async(function() {
+            this.fire('render');
+          }.bind(this), 1);
+        },
+
+        _getDiffBuilder: function(diff, comments, prefs) {
+          var diffTable = this.queryEffectiveChildren('#diffTable');
+          if (this.isImageDiff) {
+            return new GrDiffBuilderImage(diff, comments, prefs,
+                diffTable, this.baseImage, this.revisionImage);
+          } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
+            return new GrDiffBuilderSideBySide(
+                diff, comments, prefs, diffTable);
+          } else if (this.viewMode === DiffViewMode.UNIFIED) {
+            return new GrDiffBuilderUnified(
+                diff, comments, prefs, diffTable);
+          }
+          throw Error('Unsupported diff view mode: ' + this.viewMode);
+        },
+
+        _renderDiff: function() {
+          this._clearDiffContent();
+          this.emitDiff();
+          this.async(function() {
+            this.fire('render');
+          }, 1);
+        },
+
+        _clearDiffContent: function() {
+          var diffTable = this.queryEffectiveChildren('#diffTable');
+          diffTable.innerHTML = null;
+        },
+      });
+    })();
+  </script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
similarity index 100%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder.js
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
similarity index 99%
rename from polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder_test.html
rename to polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index 5905bd9..c47e05d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -19,8 +19,8 @@
 <title>gr-diff-builder</title>
 
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="gr-diff-line.js"></script>
-<script src="gr-diff-group.js"></script>
+<script src="../gr-diff/gr-diff-line.js"></script>
+<script src="../gr-diff/gr-diff-group.js"></script>
 <script src="gr-diff-builder.js"></script>
 
 <script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 1913270..cfe5d66 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -18,6 +18,7 @@
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../gr-diff-comment-thread/gr-diff-comment-thread.html">
+<link rel="import" href="../gr-diff-builder/gr-diff-builder.html">
 
 <dom-module id="gr-diff">
   <template>
@@ -153,15 +154,18 @@
         on-tap="_handleTap"
         on-mousedown="_handleMouseDown"
         on-copy="_handleCopy">
-      <table id="diffTable"></table>
+      <gr-diff-builder
+         id="diffBuilder"
+         view-mode="[[viewMode]]"
+         is-image-diff="[[isImageDiff]]"
+         base-image="[[_baseImage]]"
+         revision-image="[[_revisionImage]]">
+        <table id="diffTable"></table>
+      </gr-diff-builder>
     </div>
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-diff-line.js"></script>
   <script src="gr-diff-group.js"></script>
-  <script src="gr-diff-builder.js"></script>
-  <script src="gr-diff-builder-side-by-side.js"></script>
-  <script src="gr-diff-builder-unified.js"></script>
-  <script src="gr-diff-builder-image.js"></script>
   <script src="gr-diff.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 0056808..ea64581 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -27,12 +27,6 @@
   Polymer({
     is: 'gr-diff',
 
-    /**
-     * Fired when the diff is rendered.
-     *
-     * @event render
-     */
-
     properties: {
       changeNum: String,
       patchRange: Object,
@@ -59,7 +53,6 @@
         value: DiffViewMode.SIDE_BY_SIDE,
       },
       _diff: Object,
-      _diffBuilder: Object,
       _selectionSide: {
         type: String,
         observer: '_selectionSideChanged',
@@ -195,7 +188,7 @@
       var el = Polymer.dom(e).rootTarget;
 
       if (el.classList.contains('showContext')) {
-        this._showContext(e.detail.groups, e.detail.section);
+        this.$.diffBuilder.showContext(e.detail.groups, e.detail.section);
       } else if (el.classList.contains('lineNum')) {
         this.addDraftAtLine(el);
       }
@@ -223,8 +216,8 @@
             patchNum = this.patchRange.basePatchNum;
           }
         }
-        threadEl = this._builder.createCommentThread(this.changeNum, patchNum,
-            this.path, side, this.projectConfig);
+        threadEl = this.$.diffBuilder.createCommentThread(
+            this.changeNum, patchNum, this.path, side, this.projectConfig);
         contentEl.appendChild(threadEl);
       }
       threadEl.addDraft(opt_lineNum);
@@ -363,25 +356,6 @@
       return text;
     },
 
-    _showContext: function(newGroups, sectionEl) {
-      var groups = this._builder._groups;
-      // TODO(viktard): Polyfill findIndex for IE10.
-      var contextIndex = groups.findIndex(function(group) {
-        return group.element == sectionEl;
-      });
-
-      groups.splice.apply(groups, [contextIndex, 1].concat(newGroups));
-
-      newGroups.forEach(function(newGroup) {
-        this._builder.emitGroup(newGroup, sectionEl);
-      }.bind(this));
-      sectionEl.parentNode.removeChild(sectionEl);
-
-      this.async(function() {
-        this.fire('render', null, {bubbles: false});
-      }.bind(this), 1);
-    },
-
     _prefsChanged: function(prefsChangeRecord) {
       var prefs = prefsChangeRecord.base;
       this.customStyle['--content-width'] = prefs.line_length + 'ch';
@@ -393,17 +367,7 @@
     },
 
     _render: function() {
-      this._builder =
-          this._getDiffBuilder(this._diff, this._comments, this.prefs);
-      this._renderDiff();
-    },
-
-    _renderDiff: function() {
-      this._clearDiffContent();
-      this._builder.emitDiff();
-      this.async(function() {
-        this.fire('render', null, {bubbles: false});
-      }, 1);
+      this.$.diffBuilder.render(this._diff, this._comments, this.prefs);
     },
 
     _clearDiffContent: function() {
@@ -508,19 +472,6 @@
           this.changeNum, this._diff, this.patchRange);
     },
 
-    _getDiffBuilder: function(diff, comments, prefs) {
-      if (this.isImageDiff) {
-        return new GrDiffBuilderImage(diff, comments, prefs, this.$.diffTable,
-            this._baseImage, this._revisionImage);
-      } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
-        return new GrDiffBuilderSideBySide(diff, comments, prefs,
-            this.$.diffTable);
-      } else if (this.viewMode === DiffViewMode.UNIFIED) {
-        return new GrDiffBuilderUnified(diff, comments, prefs,
-            this.$.diffTable);
-      }
-      throw Error('Unsupported diff view mode: ' + this.viewMode);
-    },
 
     _projectConfigChanged: function(projectConfig) {
       var threadEls = this._getCommentThreads();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index aec32b6..613c7fa 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -226,8 +226,7 @@
         var rendered = function() {
           // Recognizes that it should be an image diff.
           assert.isTrue(element.isImageDiff);
-          assert.instanceOf(element._getDiffBuilder(element._diff,
-              element._comments, element.prefs), GrDiffBuilderImage);
+          assert.instanceOf(element.$.diffBuilder._builder, GrDiffBuilderImage);
 
           // Left image rendered with the parent commit's version of the file.
           var leftInmage = element.$.diffTable.querySelector('td.left img');
@@ -397,30 +396,5 @@
         });
       });
     });
-
-    suite('renderDiff', function() {
-      setup(function(done) {
-        sinon.stub(element, 'fire');
-        element._builder = {
-          emitDiff: sinon.stub(),
-        };
-        element._renderDiff();
-        flush(function() {
-          done();
-        });
-      });
-
-      teardown(function() {
-        element.fire.restore();
-      });
-
-      test('fires render', function() {
-        assert(element.fire.calledWithExactly(
-            'render', null, {bubbles: false}));
-      });
-      test('calls emitDiff on builder', function() {
-        assert(element._builder.emitDiff.calledOnce);
-      });
-    });
   });
 </script>