changeset = $changeset; return $this; } public function addButton($button) { $this->buttons[] = $button; return $this; } public function setRevisionID($revision_id) { $this->revisionID = $revision_id; return $this; } public function setSymbolIndex($symbol_index) { $this->symbolIndex = $symbol_index; return $this; } public function getID() { if (!$this->id) { $this->id = celerity_generate_unique_node_id(); } return $this->id; } public function setVsChangesetID($vs_changeset_id) { $this->vsChangesetID = $vs_changeset_id; return $this; } public function getVsChangesetID() { return $this->vsChangesetID; } public function render() { require_celerity_resource('differential-changeset-view-css'); require_celerity_resource('syntax-highlighting-css'); if ($this->revisionID) { $edit = true; } else { $edit = false; } $changeset = $this->changeset; $class = 'differential-changeset'; if (!$edit) { $class .= ' differential-changeset-immutable'; } $buttons = null; if ($this->buttons) { $buttons = '
'. implode('', $this->buttons). '
'; } $id = $this->getID(); if ($this->symbolIndex) { Javelin::initBehavior( 'repository-crossreference', array( 'container' => $id, ) + $this->symbolIndex); } $display_filename = $changeset->getDisplayFilename(); $buoyant_begin = $this->renderBuoyant($display_filename); $buoyant_end = $this->renderBuoyant(null); $output = javelin_render_tag( 'div', array( 'sigil' => 'differential-changeset', 'meta' => array( 'left' => nonempty( $this->getVsChangesetID(), $this->changeset->getID()), 'right' => $this->changeset->getID(), ), 'class' => $class, 'id' => $id, ), $buoyant_begin. phutil_render_tag( 'a', array( 'name' => $changeset->getAnchorName(), ), ''). $buttons. '

'.phutil_escape_html($display_filename).'

'. '
'. $this->renderChildren(). $buoyant_end); return $output; } private function renderBuoyant($text) { return javelin_render_tag( 'div', array( 'sigil' => 'buoyant', 'meta' => array( 'text' => $text, ), 'style' => ($text === null) // Current CSS spacing rules cause the "end" anchor to appear too // late in the display document. Shift it up a bit so we drop the // buoyant header sooner. This reduces confusion when using keystroke // navigation. ? 'bottom: 60px; position: absolute;' : null, ), ''); } }