public function render()
 {
     $this->requireResource('differential-core-view-css');
     $this->requireResource('differential-table-of-contents-css');
     $this->requireResource('phui-text-css');
     $rows = array();
     $coverage = array();
     if ($this->unitTestData) {
         $coverage_by_file = array();
         foreach ($this->unitTestData as $result) {
             $test_coverage = idx($result, 'coverage');
             if (!$test_coverage) {
                 continue;
             }
             foreach ($test_coverage as $file => $results) {
                 $coverage_by_file[$file][] = $results;
             }
         }
         foreach ($coverage_by_file as $file => $coverages) {
             $coverage[$file] = ArcanistUnitTestResult::mergeCoverage($coverages);
         }
     }
     $changesets = $this->changesets;
     $paths = array();
     foreach ($changesets as $id => $changeset) {
         $type = $changeset->getChangeType();
         $ftype = $changeset->getFileType();
         $ref = idx($this->references, $id);
         $display_file = $changeset->getDisplayFilename();
         $meta = null;
         if (DifferentialChangeType::isOldLocationChangeType($type)) {
             $away = $changeset->getAwayPaths();
             if (count($away) > 1) {
                 $meta = array();
                 if ($type == DifferentialChangeType::TYPE_MULTICOPY) {
                     $meta[] = pht('Deleted after being copied to multiple locations:');
                 } else {
                     $meta[] = pht('Copied to multiple locations:');
                 }
                 foreach ($away as $path) {
                     $meta[] = $path;
                 }
                 $meta = phutil_implode_html(phutil_tag('br'), $meta);
             } else {
                 if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) {
                     $display_file = $this->renderRename($display_file, reset($away), "→");
                 } else {
                     $meta = pht('Copied to %s', reset($away));
                 }
             }
         } else {
             if ($type == DifferentialChangeType::TYPE_MOVE_HERE) {
                 $old_file = $changeset->getOldFile();
                 $display_file = $this->renderRename($display_file, $old_file, "←");
             } else {
                 if ($type == DifferentialChangeType::TYPE_COPY_HERE) {
                     $meta = pht('Copied from %s', $changeset->getOldFile());
                 }
             }
         }
         $link = $this->renderChangesetLink($changeset, $ref, $display_file);
         $line_count = $changeset->getAffectedLineCount();
         if ($line_count == 0) {
             $lines = '';
         } else {
             $lines = ' ' . pht('(%d line(s))', $line_count);
         }
         $char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
         $chartitle = DifferentialChangeType::getFullNameForChangeType($type);
         $desc = DifferentialChangeType::getShortNameForFileType($ftype);
         $color = DifferentialChangeType::getSummaryColorForChangeType($type);
         if ($desc) {
             $desc = '(' . $desc . ')';
         }
         $pchar = $changeset->getOldProperties() === $changeset->getNewProperties() ? '' : phutil_tag('span', array('title' => pht('Properties Changed')), 'M');
         $fname = $changeset->getFilename();
         $cov = $this->renderCoverage($coverage, $fname);
         if ($cov === null) {
             $mcov = $cov = phutil_tag('em', array(), '-');
         } else {
             $mcov = phutil_tag('div', array('id' => 'differential-mcoverage-' . md5($fname), 'class' => 'differential-mcoverage-loading'), isset($this->visibleChangesets[$id]) ? pht('Loading...') : pht('?'));
         }
         if ($meta) {
             $meta = phutil_tag('div', array('class' => 'differential-toc-meta'), $meta);
         }
         if ($this->diff && $this->repository) {
             $paths[] = $changeset->getAbsoluteRepositoryPath($this->repository, $this->diff);
         }
         $char = phutil_tag('span', array('class' => 'phui-text-' . $color), $char);
         $rows[] = array($char, $pchar, $desc, array($link, $lines, $meta), $cov, $mcov);
     }
     $editor_link = null;
     if ($paths && $this->user) {
         $editor_link = $this->user->loadEditorLink($paths, 1, $this->repository->getCallsign());
         if ($editor_link) {
             $editor_link = phutil_tag('a', array('href' => $editor_link, 'class' => 'button differential-toc-edit-all'), pht('Open All in Editor'));
         }
     }
     $reveal_link = javelin_tag('a', array('sigil' => 'differential-reveal-all', 'mustcapture' => true, 'class' => 'button differential-toc-reveal-all'), pht('Show All Context'));
     $buttons = phutil_tag('div', array('class' => 'differential-toc-buttons grouped'), array($editor_link, $reveal_link));
     $table = id(new AphrontTableView($rows));
     $table->setHeaders(array('', '', '', pht('Path'), pht('Coverage (All)'), pht('Coverage (Touched)')));
     $table->setColumnClasses(array('differential-toc-char center', 'differential-toc-prop center', 'differential-toc-ftype center', 'differential-toc-file wide', 'differential-toc-cov', 'differential-toc-cov'));
     $table->setDeviceVisibility(array(true, true, true, true, false, false));
     $anchor = id(new PhabricatorAnchorView())->setAnchorName('toc')->setNavigationMarker(true);
     return id(new PHUIObjectBoxView())->setHeaderText(pht('Table of Contents'))->setTable($table)->appendChild($anchor)->appendChild($buttons);
 }
 private function renderPathChangeCharacter()
 {
     $changeset = $this->getChangeset();
     $type = $changeset->getChangeType();
     $color = DifferentialChangeType::getSummaryColorForChangeType($type);
     $char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
     $title = DifferentialChangeType::getFullNameForChangeType($type);
     return javelin_tag('span', array('sigil' => 'has-tooltip', 'meta' => array('tip' => $title, 'align' => 'E'), 'class' => 'phui-text-' . $color), $char);
 }