diff --git a/src/applications/phid/view/PHUIHandleListView.php b/src/applications/phid/view/PHUIHandleListView.php index d15b3d15c6..24104fe76d 100644 --- a/src/applications/phid/view/PHUIHandleListView.php +++ b/src/applications/phid/view/PHUIHandleListView.php @@ -1,87 +1,102 @@ <?php /** * Convenience class for rendering a list of handles. * * This class simplifies rendering a list of handles and improves loading and * caching semantics in the rendering pipeline by delaying bulk loads until the * last possible moment. */ final class PHUIHandleListView extends AphrontTagView { private $handleList; private $asInline; private $asText; private $showStateIcons; + private $glyphLimit; public function setHandleList(PhabricatorHandleList $list) { $this->handleList = $list; return $this; } public function setAsInline($inline) { $this->asInline = $inline; return $this; } public function getAsInline() { return $this->asInline; } public function setAsText($as_text) { $this->asText = $as_text; return $this; } public function getAsText() { return $this->asText; } public function setShowStateIcons($show_state_icons) { $this->showStateIcons = $show_state_icons; return $this; } public function getShowStateIcons() { return $this->showStateIcons; } + public function setGlyphLimit($glyph_limit) { + $this->glyphLimit = $glyph_limit; + return $this; + } + + public function getGlyphLimit() { + return $this->glyphLimit; + } + protected function getTagName() { if ($this->getAsText()) { return null; } else { // TODO: It would be nice to render this with a proper <ul />, at least // in block mode, but don't stir the waters up too much for now. return 'span'; } } protected function getTagContent() { $list = $this->handleList; $show_state_icons = $this->getShowStateIcons(); + $glyph_limit = $this->getGlyphLimit(); $items = array(); foreach ($list as $handle) { $view = $list->renderHandle($handle->getPHID()) ->setShowHovercard(true) ->setAsText($this->getAsText()); if ($show_state_icons) { $view->setShowStateIcon(true); } + if ($glyph_limit) { + $view->setGlyphLimit($glyph_limit); + } + $items[] = $view; } if ($this->getAsInline()) { $items = phutil_implode_html(', ', $items); } else { $items = phutil_implode_html(phutil_tag('br'), $items); } return $items; } } diff --git a/src/applications/phid/view/PHUIHandleView.php b/src/applications/phid/view/PHUIHandleView.php index 96ae7de025..fe3c62a9ac 100644 --- a/src/applications/phid/view/PHUIHandleView.php +++ b/src/applications/phid/view/PHUIHandleView.php @@ -1,98 +1,115 @@ <?php /** * Convenience class for rendering a single handle. * * This class simplifies rendering a single handle, and improves loading and * caching semantics in the rendering pipeline by loading data at the last * moment. */ final class PHUIHandleView extends AphrontView { private $handleList; private $handlePHID; private $asTag; private $asText; private $useShortName; private $showHovercard; private $showStateIcon; + private $glyphLimit; public function setHandleList(PhabricatorHandleList $list) { $this->handleList = $list; return $this; } public function setHandlePHID($phid) { $this->handlePHID = $phid; return $this; } public function setAsTag($tag) { $this->asTag = $tag; return $this; } public function setAsText($as_text) { $this->asText = $as_text; return $this; } public function setUseShortName($short) { $this->useShortName = $short; return $this; } public function setShowHovercard($hovercard) { $this->showHovercard = $hovercard; return $this; } public function setShowStateIcon($show_state_icon) { $this->showStateIcon = $show_state_icon; return $this; } public function getShowStateIcon() { return $this->showStateIcon; } + public function setGlyphLimit($glyph_limit) { + $this->glyphLimit = $glyph_limit; + return $this; + } + + public function getGlyphLimit() { + return $this->glyphLimit; + } + public function render() { $handle = $this->handleList[$this->handlePHID]; if ($this->asTag) { $tag = $handle->renderTag(); if ($this->showHovercard) { $tag->setPHID($handle->getPHID()); } return $tag; } if ($this->asText) { return $handle->getLinkName(); } if ($this->useShortName) { $name = $handle->getName(); } else { - $name = null; + $name = $handle->getLinkName(); + } + + $glyph_limit = $this->getGlyphLimit(); + if ($glyph_limit) { + $name = id(new PhutilUTF8StringTruncator()) + ->setMaximumGlyphs($glyph_limit) + ->truncateString($name); } if ($this->showHovercard) { $link = $handle->renderHovercardLink($name); } else { $link = $handle->renderLink($name); } if ($this->showStateIcon) { $icon = $handle->renderStateIcon(); $link = array($icon, ' ', $link); } return $link; } } diff --git a/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php b/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php index 8f6e4e48d7..6d76319de8 100644 --- a/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php +++ b/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php @@ -1,333 +1,334 @@ <?php final class PHUIDiffTableOfContentsItemView extends AphrontView { private $changeset; private $isVisible = true; private $anchor; private $coverage; private $coverageID; private $context; private $packages; public function setChangeset(DifferentialChangeset $changeset) { $this->changeset = $changeset; return $this; } public function getChangeset() { return $this->changeset; } public function setIsVisible($is_visible) { $this->isVisible = $is_visible; return $this; } public function getIsVisible() { return $this->isVisible; } public function setAnchor($anchor) { $this->anchor = $anchor; return $this; } public function getAnchor() { return $this->anchor; } public function setCoverage($coverage) { $this->coverage = $coverage; return $this; } public function getCoverage() { return $this->coverage; } public function setCoverageID($coverage_id) { $this->coverageID = $coverage_id; return $this; } public function getCoverageID() { return $this->coverageID; } public function setContext($context) { $this->context = $context; return $this; } public function getContext() { return $this->context; } public function setPackages(array $packages) { assert_instances_of($packages, 'PhabricatorOwnersPackage'); $this->packages = mpull($packages, null, 'getPHID'); return $this; } public function getPackages() { return $this->packages; } public function render() { $changeset = $this->getChangeset(); $cells = array(); $cells[] = $this->getContext(); $cells[] = $this->renderPathChangeCharacter(); $cells[] = $this->renderPropertyChangeCharacter(); $cells[] = $this->renderPropertyChangeDescription(); $link = $this->renderChangesetLink(); $lines = $this->renderChangesetLines(); $meta = $this->renderChangesetMetadata(); $cells[] = array( $link, $lines, $meta, ); $cells[] = $this->renderCoverage(); $cells[] = $this->renderModifiedCoverage(); $cells[] = $this->renderPackages(); return $cells; } 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); } private function renderPropertyChangeCharacter() { $changeset = $this->getChangeset(); $old = $changeset->getOldProperties(); $new = $changeset->getNewProperties(); if ($old === $new) { return null; } return javelin_tag( 'span', array( 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => pht('Properties Modified'), 'align' => 'E', 'size' => 200, ), ), 'M'); } private function renderPropertyChangeDescription() { $changeset = $this->getChangeset(); $file_type = $changeset->getFileType(); $desc = DifferentialChangeType::getShortNameForFileType($file_type); if ($desc === null) { return null; } return pht('(%s)', $desc); } private function renderChangesetLink() { $anchor = $this->getAnchor(); $changeset = $this->getChangeset(); $name = $changeset->getDisplayFilename(); $change_type = $changeset->getChangeType(); if (DifferentialChangeType::isOldLocationChangeType($change_type)) { $away = $changeset->getAwayPaths(); if (count($away) == 1) { if ($change_type == DifferentialChangeType::TYPE_MOVE_AWAY) { $right_arrow = "\xE2\x86\x92"; $name = $this->renderRename($name, head($away), $right_arrow); } } } else if ($change_type == DifferentialChangeType::TYPE_MOVE_HERE) { $left_arrow = "\xE2\x86\x90"; $name = $this->renderRename($name, $changeset->getOldFile(), $left_arrow); } return javelin_tag( 'a', array( 'href' => '#'.$anchor, 'sigil' => 'differential-load', 'meta' => array( 'id' => 'diff-'.$anchor, ), ), $name); } private function renderChangesetLines() { $changeset = $this->getChangeset(); $line_count = $changeset->getAffectedLineCount(); if (!$line_count) { return null; } return ' '.pht('(%d line(s))', $line_count); } private function renderCoverage() { $not_applicable = '-'; $coverage = $this->getCoverage(); if (!strlen($coverage)) { return $not_applicable; } $covered = substr_count($coverage, 'C'); $not_covered = substr_count($coverage, 'U'); if (!$not_covered && !$covered) { return $not_applicable; } return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered))); } private function renderModifiedCoverage() { $not_applicable = '-'; $coverage = $this->getCoverage(); if (!strlen($coverage)) { return $not_applicable; } if ($this->getIsVisible()) { $label = pht('Loading...'); } else { $label = pht('?'); } return phutil_tag( 'div', array( 'id' => $this->getCoverageID(), 'class' => 'differential-mcoverage-loading', ), $label); } private function renderChangesetMetadata() { $changeset = $this->getChangeset(); $type = $changeset->getChangeType(); $meta = array(); if (DifferentialChangeType::isOldLocationChangeType($type)) { $away = $changeset->getAwayPaths(); if (count($away) > 1) { 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; } } else { if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) { // This case is handled when we render the path. } else { $meta[] = pht('Copied to %s', head($away)); } } } else if ($type == DifferentialChangeType::TYPE_COPY_HERE) { $meta[] = pht('Copied from %s', $changeset->getOldFile()); } if (!$meta) { return null; } $meta = phutil_implode_html(phutil_tag('br'), $meta); return phutil_tag( 'div', array( 'class' => 'differential-toc-meta', ), $meta); } private function renderPackages() { $packages = $this->getPackages(); if (!$packages) { return null; } $viewer = $this->getUser(); $package_phids = mpull($packages, 'getPHID'); - return $viewer->renderHandleList($package_phids); + return $viewer->renderHandleList($package_phids) + ->setGlyphLimit(48); } private function renderRename($self, $other, $arrow) { $old = explode('/', $self); $new = explode('/', $other); $start = count($old); foreach ($old as $index => $part) { if (!isset($new[$index]) || $part != $new[$index]) { $start = $index; break; } } $end = count($old); foreach (array_reverse($old) as $from_end => $part) { $index = count($new) - $from_end - 1; if (!isset($new[$index]) || $part != $new[$index]) { $end = $from_end; break; } } $rename = '{'. implode('/', array_slice($old, $start, count($old) - $end - $start)). ' '.$arrow.' '. implode('/', array_slice($new, $start, count($new) - $end - $start)). '}'; array_splice($new, $start, count($new) - $end - $start, $rename); return implode('/', $new); } }