@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

Roughly style the new "flank" paths UI

Summary: Ref T13516. Apply basic UI styling to the new UI and make some more interaction work.

Test Plan: {F7374096}

Maniphest Tasks: T13516

Differential Revision: https://secure.phabricator.com/D21153

+374 -121
+52 -50
resources/celerity/map.php
··· 10 10 'conpherence.pkg.css' => '3c8a0668', 11 11 'conpherence.pkg.js' => '020aebcf', 12 12 'core.pkg.css' => 'a4a2417c', 13 - 'core.pkg.js' => '4355a8d3', 13 + 'core.pkg.js' => 'd092ddaf', 14 14 'differential.pkg.css' => '607c84be', 15 - 'differential.pkg.js' => '688775a9', 15 + 'differential.pkg.js' => '58e09368', 16 16 'diffusion.pkg.css' => '42c75c37', 17 17 'diffusion.pkg.js' => 'a98c0bf7', 18 18 'maniphest.pkg.css' => '35995d6d', ··· 59 59 'rsrc/css/application/countdown/timer.css' => 'bff8012f', 60 60 'rsrc/css/application/daemon/bulk-job.css' => '73af99f5', 61 61 'rsrc/css/application/dashboard/dashboard.css' => '5a205b9d', 62 + 'rsrc/css/application/diff/diff-tree-view.css' => 'ce58c3d1', 62 63 'rsrc/css/application/diff/inline-comment-summary.css' => '81eb368d', 63 64 'rsrc/css/application/differential/add-comment.css' => '7e5900d9', 64 65 'rsrc/css/application/differential/changeset-view.css' => '489b6995', ··· 155 156 'rsrc/css/phui/phui-fontkit.css' => '1ec937e5', 156 157 'rsrc/css/phui/phui-form-view.css' => '01b796c0', 157 158 'rsrc/css/phui/phui-form.css' => '1f177cb7', 158 - 'rsrc/css/phui/phui-formation-view.css' => 'e87a0801', 159 + 'rsrc/css/phui/phui-formation-view.css' => '82a3b73e', 159 160 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 160 161 'rsrc/css/phui/phui-header-view.css' => '36c86a58', 161 162 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', ··· 378 379 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be', 379 380 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 380 381 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8', 381 - 'rsrc/js/application/diff/DiffChangeset.js' => 'd1eda7b4', 382 - 'rsrc/js/application/diff/DiffChangesetList.js' => '469beba0', 382 + 'rsrc/js/application/diff/DiffChangeset.js' => 'ea6e377d', 383 + 'rsrc/js/application/diff/DiffChangesetList.js' => '5a351998', 383 384 'rsrc/js/application/diff/DiffInline.js' => '16e97ebc', 384 - 'rsrc/js/application/diff/DiffPathView.js' => 'e5166692', 385 - 'rsrc/js/application/diff/DiffTreeView.js' => '4055adeb', 385 + 'rsrc/js/application/diff/DiffPathView.js' => '8337f4c7', 386 + 'rsrc/js/application/diff/DiffTreeView.js' => 'a5823e4d', 386 387 'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17', 387 388 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 388 389 'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2', ··· 457 458 'rsrc/js/core/FileUpload.js' => 'ab85e184', 458 459 'rsrc/js/core/Hovercard.js' => '074f0783', 459 460 'rsrc/js/core/KeyboardShortcut.js' => '1a844c06', 460 - 'rsrc/js/core/KeyboardShortcutManager.js' => 'ef926938', 461 + 'rsrc/js/core/KeyboardShortcutManager.js' => '81debc48', 461 462 'rsrc/js/core/MultirowRowManager.js' => '5b54c823', 462 463 'rsrc/js/core/Notification.js' => 'a9b91e3f', 463 464 'rsrc/js/core/Prefab.js' => '5793d835', ··· 529 530 'rsrc/js/phuix/PHUIXDropdownMenu.js' => '7acfd98b', 530 531 'rsrc/js/phuix/PHUIXExample.js' => 'c2c500a7', 531 532 'rsrc/js/phuix/PHUIXFormControl.js' => '38c1f3fb', 532 - 'rsrc/js/phuix/PHUIXFormationColumnView.js' => '8afd2cb1', 533 + 'rsrc/js/phuix/PHUIXFormationColumnView.js' => '4bcc1f78', 533 534 'rsrc/js/phuix/PHUIXFormationFlankView.js' => '6648270a', 534 535 'rsrc/js/phuix/PHUIXFormationView.js' => 'cef53b3e', 535 536 'rsrc/js/phuix/PHUIXIconView.js' => 'a5257c4e', ··· 561 562 'conpherence-thread-manager' => 'aec8e38c', 562 563 'conpherence-transaction-css' => '3a3f5e7e', 563 564 'd3' => '9d068042', 565 + 'diff-tree-view-css' => 'ce58c3d1', 564 566 'differential-changeset-view-css' => '489b6995', 565 567 'differential-core-view-css' => '7300a73e', 566 568 'differential-revision-add-comment-css' => '7e5900d9', ··· 780 782 'phabricator-darklog' => '3b869402', 781 783 'phabricator-darkmessage' => '26cd4b73', 782 784 'phabricator-dashboard-css' => '5a205b9d', 783 - 'phabricator-diff-changeset' => 'd1eda7b4', 784 - 'phabricator-diff-changeset-list' => '469beba0', 785 + 'phabricator-diff-changeset' => 'ea6e377d', 786 + 'phabricator-diff-changeset-list' => '5a351998', 785 787 'phabricator-diff-inline' => '16e97ebc', 786 - 'phabricator-diff-path-view' => 'e5166692', 787 - 'phabricator-diff-tree-view' => '4055adeb', 788 + 'phabricator-diff-path-view' => '8337f4c7', 789 + 'phabricator-diff-tree-view' => 'a5823e4d', 788 790 'phabricator-drag-and-drop-file-upload' => '4370900d', 789 791 'phabricator-draggable-list' => '0169e425', 790 792 'phabricator-fatal-config-template-css' => '20babf50', ··· 794 796 'phabricator-filetree-view-css' => '56cdd875', 795 797 'phabricator-flag-css' => '2b77be8d', 796 798 'phabricator-keyboard-shortcut' => '1a844c06', 797 - 'phabricator-keyboard-shortcut-manager' => 'ef926938', 799 + 'phabricator-keyboard-shortcut-manager' => '81debc48', 798 800 'phabricator-main-menu-view' => 'bcec20f0', 799 801 'phabricator-nav-view-css' => 'f8a0c1bf', 800 802 'phabricator-notification' => 'a9b91e3f', ··· 852 854 'phui-fontkit-css' => '1ec937e5', 853 855 'phui-form-css' => '1f177cb7', 854 856 'phui-form-view-css' => '01b796c0', 855 - 'phui-formation-view-css' => 'e87a0801', 857 + 'phui-formation-view-css' => '82a3b73e', 856 858 'phui-head-thing-view-css' => 'd7f293df', 857 859 'phui-header-view-css' => '36c86a58', 858 860 'phui-hovercard' => '074f0783', ··· 895 897 'phuix-button-view' => '55a24e84', 896 898 'phuix-dropdown-menu' => '7acfd98b', 897 899 'phuix-form-control-view' => '38c1f3fb', 898 - 'phuix-formation-column-view' => '8afd2cb1', 900 + 'phuix-formation-column-view' => '4bcc1f78', 899 901 'phuix-formation-flank-view' => '6648270a', 900 902 'phuix-formation-view' => 'cef53b3e', 901 903 'phuix-icon-view' => 'a5257c4e', ··· 1267 1269 'phabricator-drag-and-drop-file-upload', 1268 1270 'phabricator-draggable-list', 1269 1271 ), 1270 - '4055adeb' => array( 1271 - 'javelin-dom', 1272 - ), 1273 1272 '407ee861' => array( 1274 1273 'javelin-behavior', 1275 1274 'javelin-uri', ··· 1319 1318 'javelin-util', 1320 1319 'phabricator-busy', 1321 1320 ), 1322 - '469beba0' => array( 1323 - 'javelin-install', 1324 - 'phuix-button-view', 1325 - 'phabricator-diff-tree-view', 1326 - ), 1327 1321 '47a0728b' => array( 1328 1322 'javelin-behavior', 1329 1323 'javelin-dom', ··· 1368 1362 'javelin-dom', 1369 1363 'javelin-util', 1370 1364 'javelin-request', 1365 + ), 1366 + '4bcc1f78' => array( 1367 + 'javelin-install', 1368 + 'javelin-dom', 1371 1369 ), 1372 1370 '4dffaeb2' => array( 1373 1371 'javelin-behavior', ··· 1473 1471 'javelin-stratcom', 1474 1472 'javelin-dom', 1475 1473 'javelin-history', 1474 + ), 1475 + '5a351998' => array( 1476 + 'javelin-install', 1477 + 'phuix-button-view', 1478 + 'phabricator-diff-tree-view', 1476 1479 ), 1477 1480 '5a6f6a06' => array( 1478 1481 'javelin-behavior', ··· 1647 1650 'javelin-install', 1648 1651 'javelin-typeahead-source', 1649 1652 ), 1653 + '81debc48' => array( 1654 + 'javelin-install', 1655 + 'javelin-util', 1656 + 'javelin-stratcom', 1657 + 'javelin-dom', 1658 + 'javelin-vector', 1659 + ), 1660 + '8337f4c7' => array( 1661 + 'javelin-dom', 1662 + ), 1650 1663 83754533 => array( 1651 1664 'javelin-install', 1652 1665 'javelin-util', ··· 1690 1703 'javelin-workflow', 1691 1704 'javelin-dom', 1692 1705 'phabricator-draggable-list', 1693 - ), 1694 - '8afd2cb1' => array( 1695 - 'javelin-install', 1696 - 'javelin-dom', 1697 1706 ), 1698 1707 '8b5c7d65' => array( 1699 1708 'javelin-behavior', ··· 1864 1873 ), 1865 1874 'a5257c4e' => array( 1866 1875 'javelin-install', 1876 + 'javelin-dom', 1877 + ), 1878 + 'a5823e4d' => array( 1867 1879 'javelin-dom', 1868 1880 ), 1869 1881 'a61c2d11' => array( ··· 2096 2108 'javelin-workflow', 2097 2109 'javelin-util', 2098 2110 ), 2099 - 'd1eda7b4' => array( 2100 - 'javelin-dom', 2101 - 'javelin-util', 2102 - 'javelin-stratcom', 2103 - 'javelin-install', 2104 - 'javelin-workflow', 2105 - 'javelin-router', 2106 - 'javelin-behavior-device', 2107 - 'javelin-vector', 2108 - 'phabricator-diff-inline', 2109 - 'phabricator-diff-path-view', 2110 - ), 2111 2111 'd3799cb4' => array( 2112 2112 'javelin-install', 2113 2113 ), ··· 2134 2134 'javelin-dom', 2135 2135 'phuix-dropdown-menu', 2136 2136 ), 2137 - 'e5166692' => array( 2138 - 'javelin-dom', 2139 - ), 2140 2137 'e5bdb730' => array( 2141 2138 'javelin-behavior', 2142 2139 'javelin-stratcom', ··· 2164 2161 'javelin-install', 2165 2162 'javelin-event', 2166 2163 ), 2164 + 'ea6e377d' => array( 2165 + 'javelin-dom', 2166 + 'javelin-util', 2167 + 'javelin-stratcom', 2168 + 'javelin-install', 2169 + 'javelin-workflow', 2170 + 'javelin-router', 2171 + 'javelin-behavior-device', 2172 + 'javelin-vector', 2173 + 'phabricator-diff-inline', 2174 + 'phabricator-diff-path-view', 2175 + ), 2167 2176 'ebe83a6b' => array( 2168 2177 'javelin-install', 2169 2178 ), ··· 2177 2186 'javelin-behavior', 2178 2187 'javelin-dom', 2179 2188 'javelin-stratcom', 2180 - ), 2181 - 'ef926938' => array( 2182 - 'javelin-install', 2183 - 'javelin-util', 2184 - 'javelin-stratcom', 2185 - 'javelin-dom', 2186 - 'javelin-vector', 2187 2189 ), 2188 2190 'f166c949' => array( 2189 2191 'javelin-behavior',
+26 -35
src/applications/differential/engine/DifferentialFileTreeEngine.php
··· 43 43 return $content; 44 44 } 45 45 46 + require_celerity_resource('diff-tree-view-css'); 47 + 46 48 $width = $this->getWidth(); 47 49 $is_visible = $this->getIsVisible(); 48 50 49 51 $formation_view = new PHUIFormationView(); 50 52 51 53 $flank_view = $formation_view->newFlankColumn() 52 - ->setHeaderText(pht('Affected Paths')) 54 + ->setHeaderText(pht('Paths')) 53 55 ->setIsResizable(true) 54 56 ->setIsFixed(true) 55 57 ->setIsVisible($is_visible) ··· 60 62 $viewer = $this->getViewer(); 61 63 if ($viewer->isLoggedIn()) { 62 64 $flank_view 65 + ->setExpanderTooltip(pht('Show Paths Panel')) 63 66 ->setVisibleSettingKey($this->getVisibleSettingKey()) 64 67 ->setWidthSettingKey($this->getWidthSettingKey()); 65 68 } 66 69 67 - $flank_view->setHead( 68 - array( 69 - phutil_tag('div', array(), 70 - array( 71 - id(new PHUIIconView())->setIcon('fa-list'), 72 - pht('Table of Contents'), 73 - '[t]', 74 - )), 75 - )); 70 + $head_view = id(new PHUIListView()) 71 + ->addMenuItem( 72 + id(new PHUIListItemView()) 73 + ->setIcon('fa-list') 74 + ->setName(pht('Table of Contents')) 75 + ->setKeyCommand('t') 76 + ->setHref('#')); 77 + $flank_view->setHead($head_view); 76 78 77 - $flank_view->setBody( 78 - phutil_tag( 79 - 'div', 80 - array( 81 - 'class' => 'phui-flank-loading', 82 - ), 83 - pht('Loading...'))); 84 - 85 - $flank_view->setTail( 86 - array( 87 - phutil_tag('div', array(), 88 - array( 89 - id(new PHUIIconView())->setIcon('fa-chevron-left'), 90 - pht('Hide Panel'), 91 - '[f]', 92 - )), 93 - phutil_tag( 94 - 'div', 95 - array(), 96 - array( 97 - id(new PHUIIconView())->setIcon('fa-keyboard-o'), 98 - pht('Keyboard Reference'), 99 - '[?]', 100 - )), 101 - )); 79 + $tail_view = id(new PHUIListView()) 80 + ->addMenuItem( 81 + id(new PHUIListItemView()) 82 + ->setIcon('fa-chevron-left') 83 + ->setName(pht('Hide Panel')) 84 + ->setKeyCommand('f') 85 + ->setHref('#')) 86 + ->addMenuItem( 87 + id(new PHUIListItemView()) 88 + ->setIcon('fa-keyboard-o') 89 + ->setName(pht('Keyboard Reference')) 90 + ->setKeyCommand('?') 91 + ->setHref('#')); 92 + $flank_view->setTail($tail_view); 102 93 103 94 $main_column = $formation_view->newContentColumn() 104 95 ->appendChild($content);
+1 -1
src/applications/differential/view/DifferentialChangesetDetailView.php
··· 287 287 return null; 288 288 } 289 289 290 - return '/settings/panel/display/'; 290 + return '/settings/panel/editor/'; 291 291 } 292 292 293 293 }
+10
src/view/formation/PHUIFormationColumnDynamicView.php
··· 10 10 private $visibleSettingKey; 11 11 private $minimumWidth; 12 12 private $maximumWidth; 13 + private $expanderTooltip; 14 + 15 + public function setExpanderTooltip($expander_tooltip) { 16 + $this->expanderTooltip = $expander_tooltip; 17 + return $this; 18 + } 19 + 20 + public function getExpanderTooltip() { 21 + return $this->expanderTooltip; 22 + } 13 23 14 24 public function setIsVisible($is_visible) { 15 25 $this->isVisible = $is_visible;
+4
src/view/formation/PHUIFormationColumnView.php
··· 50 50 return null; 51 51 } 52 52 53 + public function getExpanderTooltip() { 54 + return null; 55 + } 56 + 53 57 }
+11 -6
src/view/formation/PHUIFormationView.php
··· 167 167 private function generateExpanders(array $items) { 168 168 foreach ($items as $item) { 169 169 $control_item = $item->getControlItem(); 170 - if ($control_item) { 171 - $expander = $this->newColumnExpanderView(); 170 + if (!$control_item) { 171 + continue; 172 + } 173 + 174 + $expander = $this->newColumnExpanderView(); 175 + 176 + $tip = $item->getColumn()->getExpanderTooltip(); 177 + $expander->setTooltip($tip); 172 178 173 - $expander->setColumnItem($item); 174 - $item->setExpander($expander); 179 + $expander->setColumnItem($item); 180 + $item->setExpander($expander); 175 181 176 - $control_item->appendExpander($expander); 177 - } 182 + $control_item->appendExpander($expander); 178 183 } 179 184 180 185 return $items;
+27 -4
src/view/phui/PHUIListItemView.php
··· 36 36 private $count; 37 37 private $rel; 38 38 private $dropdownMenu; 39 + private $keyCommand; 39 40 40 41 public function setOpenInNewWindow($open_in_new_window) { 41 42 $this->openInNewWindow = $open_in_new_window; ··· 220 221 return 'li'; 221 222 } 222 223 224 + public function setKeyCommand($key_command) { 225 + $this->keyCommand = $key_command; 226 + return $this; 227 + } 228 + 229 + public function getKeyCommand() { 230 + return $this->keyCommand; 231 + } 232 + 223 233 protected function getTagAttributes() { 224 234 $classes = array(); 225 235 $classes[] = 'phui-list-item-view'; ··· 277 287 $name = null; 278 288 $icon = null; 279 289 $meta = null; 280 - $sigil = null; 290 + $sigil = array(); 281 291 282 292 if ($this->name) { 283 293 if ($this->getRenderNameAsTooltip()) { 284 294 Javelin::initBehavior('phabricator-tooltips'); 285 - $sigil = 'has-tooltip'; 295 + $sigil[] = 'has-tooltip'; 286 296 $meta = array( 287 297 'tip' => $this->name, 288 298 'align' => 'E', ··· 290 300 } else { 291 301 if ($this->tooltip) { 292 302 Javelin::initBehavior('phabricator-tooltips'); 293 - $sigil = 'has-tooltip'; 303 + $sigil[] = 'has-tooltip'; 294 304 $meta = array( 295 305 'tip' => $this->tooltip, 296 306 'align' => 'E', ··· 383 393 384 394 $icons = $this->getIcons(); 385 395 396 + $key_command = null; 397 + if ($this->keyCommand) { 398 + $key_command = phutil_tag( 399 + 'span', 400 + array( 401 + 'class' => 'keyboard-shortcut-key', 402 + ), 403 + $this->keyCommand); 404 + $sigil[] = 'has-key-command'; 405 + $meta['keyCommand'] = $this->keyCommand; 406 + } 407 + 386 408 $list_item = javelin_tag( 387 409 $this->href ? 'a' : 'div', 388 410 array( 389 411 'href' => $this->href, 390 412 'class' => implode(' ', $classes), 391 413 'meta' => $meta, 392 - 'sigil' => $sigil, 414 + 'sigil' => implode(' ', $sigil), 393 415 'target' => $this->getOpenInNewWindow() ? '_blank' : null, 394 416 'rel' => $this->rel, 395 417 ), ··· 400 422 $this->renderChildren(), 401 423 $name, 402 424 $count, 425 + $key_command, 403 426 $caret, 404 427 )); 405 428
+47
webroot/rsrc/css/application/diff/diff-tree-view.css
··· 1 + /** 2 + * @provides diff-tree-view-css 3 + */ 4 + 5 + .diff-tree-view { 6 + margin: 4px; 7 + } 8 + 9 + .diff-tree-path { 10 + position: relative; 11 + height: 20px; 12 + color: {$greytext}; 13 + line-height: 20px; 14 + } 15 + 16 + .diff-tree-path-icon { 17 + position: absolute; 18 + width: 20px; 19 + height: 20px; 20 + text-align: center; 21 + } 22 + 23 + .diff-tree-path-name { 24 + margin-left: 24px; 25 + margin-right: 24px; 26 + white-space: nowrap; 27 + overflow: hidden; 28 + text-overflow: ellipsis; 29 + } 30 + 31 + .diff-tree-path-changeset { 32 + cursor: pointer; 33 + color: {$darkbluetext}; 34 + } 35 + 36 + .diff-tree-path-focused { 37 + background: {$darkgreybackground}; 38 + } 39 + 40 + .diff-tree-path-selected { 41 + background: {$yellow}; 42 + } 43 + 44 + .device-desktop .diff-tree-path-changeset:hover { 45 + background: {$lightblueborder}; 46 + transition: 0.1s; 47 + }
+36 -4
webroot/rsrc/css/phui/phui-formation-view.css
··· 54 54 55 55 .phui-flank-header { 56 56 padding: 8px; 57 - background: {$greybackground}; 57 + background: {$bluebackground}; 58 58 border-bottom: 1px solid {$lightgreyborder}; 59 59 } 60 60 ··· 144 144 width: 100%; 145 145 } 146 146 147 - .phui-flank-loading { 148 - color: {$lightgreytext}; 147 + .phui-flank-view .phui-list-view { 148 + margin: 4px; 149 + } 150 + 151 + .phui-flank-view .phui-list-item-view { 152 + height: 20px; 153 + padding: 4px 0; 154 + } 155 + 156 + .phui-flank-view .phui-list-item-view .phui-icon-view { 157 + width: 20px; 158 + height: 20px; 149 159 text-align: center; 150 - margin: 16px; 160 + margin-right: 4px; 161 + } 162 + 163 + .phui-flank-view .phui-list-item-view .phui-list-item-href { 164 + display: block; 165 + color: {$darkbluetext}; 166 + text-decoration: none; 167 + } 168 + 169 + .device-desktop .phui-flank-view .phui-list-item-view:hover { 170 + background: {$lightblueborder}; 171 + transition: 0.1s; 172 + } 173 + 174 + .phui-flank-view .keyboard-shortcut-key { 175 + position: absolute; 176 + right: 4px; 177 + top: 4px; 178 + height: 18px; 179 + width: 18px; 180 + line-height: 18px; 181 + padding: 0; 182 + color: {$lightgreytext}; 151 183 }
+6 -1
webroot/rsrc/js/application/diff/DiffChangeset.js
··· 897 897 898 898 getPathView: function() { 899 899 if (!this._pathView) { 900 - this._pathView = new JX.DiffPathView() 900 + var view = new JX.DiffPathView() 901 901 .setChangeset(this) 902 902 .setPath(this._pathParts); 903 + 904 + view.getIcon() 905 + .setIcon(this.getIcon()); 906 + 907 + this._pathView = view; 903 908 } 904 909 905 910 return this._pathView;
+21 -2
webroot/rsrc/js/application/diff/DiffChangesetList.js
··· 194 194 'Jump to previous inline comment, including collapsed comments.'); 195 195 this._installJumpKey('P', label, -1, 'comment', true); 196 196 197 + var formation = this.getFormationView(); 198 + if (formation) { 199 + var filetree = formation.getColumn(0); 200 + var toggletree = JX.bind(filetree, filetree.toggleVisibility); 201 + this._installKey('f', 'diff-vis', label, toggletree); 202 + } 203 + 197 204 if (!standalone) { 198 205 label = pht('Hide or show the current file.'); 199 206 this._installKey('h', 'diff-vis', label, this._onkeytogglefile); ··· 683 690 return; 684 691 } 685 692 693 + var tree = this._getTreeView(); 694 + if (cursor.changeset) { 695 + tree.setSelectedPath(cursor.changeset.getPathView()); 696 + } else { 697 + tree.setSelectedPath(null); 698 + } 699 + 686 700 this.setFocus(cursor.nodes.begin, cursor.nodes.end); 687 701 688 702 if (scroll) { ··· 1139 1153 }, 1140 1154 1141 1155 setFocus: function(node, extended_node) { 1156 + if (!node) { 1157 + var tree = this._getTreeView(); 1158 + tree.setSelectedPath(null); 1159 + } 1160 + 1142 1161 this._focusStart = node; 1143 1162 this._focusEnd = extended_node; 1144 1163 this._redrawFocus(); ··· 1493 1512 if (!changeset) { 1494 1513 this._bannerChangeset = null; 1495 1514 JX.DOM.remove(node); 1496 - tree.setSelectedPath(null); 1515 + tree.setFocusedPath(null); 1497 1516 1498 1517 if (formation) { 1499 1518 formation.repaint(); ··· 1513 1532 for (var ii = 0; ii < paths.length; ii++) { 1514 1533 var path = paths[ii]; 1515 1534 if (path.getChangeset() === changeset) { 1516 - tree.setSelectedPath(path); 1535 + tree.setFocusedPath(path); 1517 1536 } 1518 1537 } 1519 1538
+77 -15
webroot/rsrc/js/application/diff/DiffPathView.js
··· 9 9 construct: function() { 10 10 }, 11 11 12 - properties: { 13 - changeset: null 14 - }, 15 - 16 12 members: { 17 13 _node: null, 18 14 _path: null, 19 15 _depth: 0, 20 16 _selected: false, 17 + _focused: false, 18 + _icon: null, 19 + 20 + _indentNode: null, 21 + _pathNode: null, 22 + _changeset: null, 21 23 22 24 getNode: function() { 23 25 if (!this._node) { 24 - this._node = JX.$N('li'); 26 + var attrs = { 27 + className: 'diff-tree-path' 28 + }; 29 + 30 + this._node = JX.$N('li', attrs, this._getIndentNode()); 25 31 26 32 var onclick = JX.bind(this, this._onclick); 27 33 JX.DOM.listen(this._node, 'click', null, onclick); 28 34 } 29 35 return this._node; 36 + }, 37 + 38 + getIcon: function() { 39 + if (!this._icon) { 40 + this._icon = new JX.PHUIXIconView(); 41 + } 42 + return this._icon; 30 43 }, 31 44 32 45 setPath: function(path) { 33 46 this._path = path; 34 - this._redraw(); 47 + 48 + var display = this._path[this._path.length - 1]; 49 + JX.DOM.setContent(this._getPathNode(), display); 50 + 51 + return this; 52 + }, 53 + 54 + setChangeset: function(changeset) { 55 + this._changeset = changeset; 56 + 57 + var node = this.getNode(); 58 + JX.DOM.alterClass(node, 'diff-tree-path-changeset', !!changeset); 59 + 35 60 return this; 61 + }, 62 + 63 + getChangeset: function() { 64 + return this._changeset; 36 65 }, 37 66 38 67 getPath: function() { ··· 41 70 42 71 setDepth: function(depth) { 43 72 this._depth = depth; 44 - this._redraw(); 73 + 74 + this._getIndentNode().style.marginLeft = (8 * this._depth) + 'px'; 75 + 45 76 return this; 46 77 }, 47 78 48 79 setIsSelected: function(selected) { 49 80 this._selected = selected; 50 - this._redraw(); 81 + 82 + var node = this.getNode(); 83 + JX.DOM.alterClass(node, 'diff-tree-path-selected', this._selected); 84 + 85 + return this; 86 + }, 87 + 88 + setIsFocused: function(focused) { 89 + this._focused = focused; 90 + 91 + var node = this.getNode(); 92 + JX.DOM.alterClass(node, 'diff-tree-path-focused', this._focused); 93 + 51 94 return this; 52 95 }, 53 96 ··· 64 107 e.kill(); 65 108 }, 66 109 67 - _redraw: function() { 68 - var node = this.getNode(); 110 + _getIndentNode: function() { 111 + if (!this._indentNode) { 112 + var content = [ 113 + this._getIconNode(), 114 + this._getPathNode(), 115 + ]; 69 116 70 - node.style.paddingLeft = (8 * this._depth) + 'px'; 117 + this._indentNode = JX.$N('div', {}, content); 118 + } 71 119 72 - var display = this._path[this._path.length - 1]; 120 + return this._indentNode; 121 + }, 73 122 74 - if (this._selected) { 75 - display = ['*', display]; 123 + _getPathNode: function() { 124 + if (!this._pathNode) { 125 + var attrs = { 126 + className: 'diff-tree-path-name' 127 + }; 128 + this._pathNode = JX.$N('div', attrs); 76 129 } 130 + return this._pathNode; 131 + }, 77 132 78 - JX.DOM.setContent(node, display); 133 + _getIconNode: function() { 134 + if (!this._iconNode) { 135 + var attrs = { 136 + className: 'diff-tree-path-icon', 137 + }; 138 + this._iconNode = JX.$N('div', attrs, this.getIcon().getNode()); 139 + } 140 + return this._iconNode; 79 141 } 80 142 81 143 }
+25 -1
webroot/rsrc/js/application/diff/DiffTreeView.js
··· 21 21 _dirty: false, 22 22 _paths: null, 23 23 _selectedPath: null, 24 + _focusedPath: null, 24 25 25 26 getNode: function() { 26 27 if (!this._node) { 27 - this._node = JX.$N('ul'); 28 + var attrs = { 29 + className: 'diff-tree-view' 30 + }; 31 + 32 + this._node = JX.$N('ul', attrs); 28 33 } 29 34 30 35 if (this._dirty) { ··· 64 69 return this; 65 70 }, 66 71 72 + setFocusedPath: function(path) { 73 + if (this._focusedPath) { 74 + this._focusedPath.setIsFocused(false); 75 + this._focusedPath = null; 76 + } 77 + 78 + if (path) { 79 + path.setIsFocused(true); 80 + } 81 + 82 + this._focusedPath = path; 83 + 84 + return this; 85 + }, 86 + 67 87 redraw: function() { 68 88 if (!this._dirty) { 69 89 return; ··· 83 103 if (!path) { 84 104 path = new JX.DiffPathView() 85 105 .setPath(tree.parts); 106 + 107 + path.getIcon() 108 + .setIcon('fa-folder-open-o'); 109 + 86 110 tree.pathObject = path; 87 111 } 88 112
+22 -2
webroot/rsrc/js/core/KeyboardShortcutManager.js
··· 16 16 JX.Stratcom.listen('keypress', null, JX.bind(this, this._onkeypress)); 17 17 JX.Stratcom.listen('keydown', null, JX.bind(this, this._onkeydown)); 18 18 JX.Stratcom.listen('keyup', null, JX.bind(this, this._onkeyup)); 19 + 20 + var onelement = JX.bind(this, this._onelement); 21 + JX.Stratcom.listen('click', 'has-key-command', onelement); 19 22 }, 20 23 21 24 statics : { ··· 118 121 119 122 var key = this._getKey(e); 120 123 124 + var handled = this._handleKey(key); 125 + 126 + if (handled) { 127 + e.kill(); 128 + } 129 + }, 130 + 131 + _handleKey: function(key) { 121 132 var shortcuts = this._shortcuts; 133 + 122 134 for (var ii = 0; ii < shortcuts.length; ii++) { 123 135 var keys = shortcuts[ii].getKeys(); 124 136 for (var jj = 0; jj < keys.length; jj++) { 125 137 if (keys[jj] == key) { 126 138 shortcuts[ii].getHandler()(this); 127 - e.kill(); // Consume the event 128 - return; 139 + return true; 129 140 } 130 141 } 131 142 } 143 + 144 + return false; 132 145 }, 146 + 133 147 _onkeydown : function(e) { 134 148 this._handleTooltipKeyEvent(e, true); 135 149 ··· 142 156 }, 143 157 _getKey : function(e) { 144 158 return e.getSpecialKey() || String.fromCharCode(e.getRawEvent().charCode); 159 + }, 160 + _onelement: function(e) { 161 + var data = e.getNodeData('has-key-command'); 162 + this._handleKey(data.keyCommand); 163 + 164 + e.kill(); 145 165 }, 146 166 _handleTooltipKeyEvent : function(e, is_keydown) { 147 167 if (e.getRawEvent().keyCode != 18) {
+9
webroot/rsrc/js/phuix/PHUIXFormationColumnView.js
··· 135 135 136 136 _setVisibility: function(visible, e) { 137 137 e.kill(); 138 + this.setVisibility(visible); 139 + }, 138 140 141 + toggleVisibility: function() { 142 + return this.setVisibility(!this.getIsVisible()); 143 + }, 144 + 145 + setVisibility: function(visible) { 139 146 this.setIsVisible(visible); 140 147 this.repaint(); 141 148 ··· 143 150 if (visible_key) { 144 151 this._adjustSetting(visible_key, visible ? 1 : 0); 145 152 } 153 + 154 + return this; 146 155 }, 147 156 148 157 _adjustSetting: function(key, value) {