| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 /** | 29 /** |
| 30 * @unrestricted | 30 * @unrestricted |
| 31 */ | 31 */ |
| 32 UI.TreeOutline = class extends Common.Object { | 32 UI.TreeOutline = class extends Common.Object { |
| 33 /** | 33 constructor() { |
| 34 * @param {boolean=} nonFocusable | |
| 35 */ | |
| 36 constructor(nonFocusable) { | |
| 37 super(); | 34 super(); |
| 38 this._createRootElement(); | 35 this._createRootElement(); |
| 39 | 36 |
| 37 /** @type {?UI.TreeElement} */ |
| 40 this.selectedTreeElement = null; | 38 this.selectedTreeElement = null; |
| 41 this.expandTreeElementsWhenArrowing = false; | 39 this.expandTreeElementsWhenArrowing = false; |
| 42 /** @type {?function(!UI.TreeElement, !UI.TreeElement):number} */ | 40 /** @type {?function(!UI.TreeElement, !UI.TreeElement):number} */ |
| 43 this._comparator = null; | 41 this._comparator = null; |
| 44 | 42 |
| 45 this.contentElement = this._rootElement._childrenListNode; | 43 this.contentElement = this._rootElement._childrenListNode; |
| 46 this.contentElement.addEventListener('keydown', this._treeKeyDown.bind(this)
, true); | 44 this.contentElement.addEventListener('keydown', this._treeKeyDown.bind(this)
, true); |
| 47 this.contentElement.addEventListener('focus', setFocused.bind(this, true), f
alse); | |
| 48 this.contentElement.addEventListener('blur', setFocused.bind(this, false), f
alse); | |
| 49 | 45 |
| 50 this.setFocusable(!nonFocusable); | 46 this._focusable = true; |
| 51 | 47 this.setFocusable(this._focusable); |
| 48 if (this._focusable) |
| 49 this.contentElement.setAttribute('tabIndex', -1); |
| 52 this.element = this.contentElement; | 50 this.element = this.contentElement; |
| 53 | 51 |
| 54 // Adjust to allow computing margin-left for the selection element. | 52 // Adjust to allow computing margin-left for the selection element. |
| 55 // Check the padding-left for the li element for correct value. | 53 // Check the padding-left for the li element for correct value. |
| 56 this._paddingSize = 0; | 54 this._paddingSize = 0; |
| 57 | |
| 58 /** | |
| 59 * @param {boolean} isFocused | |
| 60 * @this {UI.TreeOutline} | |
| 61 */ | |
| 62 function setFocused(isFocused) { | |
| 63 this._focused = isFocused; | |
| 64 if (this.selectedTreeElement) | |
| 65 this.selectedTreeElement._setFocused(this._focused); | |
| 66 } | |
| 67 } | 55 } |
| 68 | 56 |
| 69 _createRootElement() { | 57 _createRootElement() { |
| 70 this._rootElement = new UI.TreeElement(); | 58 this._rootElement = new UI.TreeElement(); |
| 71 this._rootElement.treeOutline = this; | 59 this._rootElement.treeOutline = this; |
| 72 this._rootElement.root = true; | 60 this._rootElement.root = true; |
| 73 this._rootElement.selectable = false; | 61 this._rootElement.selectable = false; |
| 74 this._rootElement.expanded = true; | 62 this._rootElement.expanded = true; |
| 75 this._rootElement._childrenListNode.classList.remove('children'); | 63 this._rootElement._childrenListNode.classList.remove('children'); |
| 76 } | 64 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 * @param {?function(!UI.TreeElement, !UI.TreeElement):number} comparator | 131 * @param {?function(!UI.TreeElement, !UI.TreeElement):number} comparator |
| 144 */ | 132 */ |
| 145 setComparator(comparator) { | 133 setComparator(comparator) { |
| 146 this._comparator = comparator; | 134 this._comparator = comparator; |
| 147 } | 135 } |
| 148 | 136 |
| 149 /** | 137 /** |
| 150 * @param {boolean} focusable | 138 * @param {boolean} focusable |
| 151 */ | 139 */ |
| 152 setFocusable(focusable) { | 140 setFocusable(focusable) { |
| 153 if (focusable) | 141 if (focusable) { |
| 154 this.contentElement.setAttribute('tabIndex', 0); | 142 this._focusable = true; |
| 155 else | 143 this.contentElement.setAttribute('tabIndex', -1); |
| 144 if (this.selectedTreeElement) |
| 145 this.selectedTreeElement._setFocusable(true); |
| 146 } else { |
| 147 this._focusable = false; |
| 156 this.contentElement.removeAttribute('tabIndex'); | 148 this.contentElement.removeAttribute('tabIndex'); |
| 149 if (this.selectedTreeElement) |
| 150 this.selectedTreeElement._setFocusable(false); |
| 151 } |
| 157 } | 152 } |
| 158 | 153 |
| 159 focus() { | 154 focus() { |
| 160 this.contentElement.focus(); | 155 if (this.selectedTreeElement) |
| 156 this.selectedTreeElement.listItemElement.focus(); |
| 157 else |
| 158 this.contentElement.focus(); |
| 161 } | 159 } |
| 162 | 160 |
| 163 /** | 161 /** |
| 164 * @param {!UI.TreeElement} element | 162 * @param {!UI.TreeElement} element |
| 165 */ | 163 */ |
| 166 _bindTreeElement(element) { | 164 _bindTreeElement(element) { |
| 167 if (element.treeOutline) | 165 if (element.treeOutline) |
| 168 console.error('Binding element for the second time: ' + new Error().stack)
; | 166 console.error('Binding element for the second time: ' + new Error().stack)
; |
| 169 element.treeOutline = this; | 167 element.treeOutline = this; |
| 170 element.onbind(); | 168 element.onbind(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 * @param {number} paddingSize | 214 * @param {number} paddingSize |
| 217 */ | 215 */ |
| 218 setPaddingSize(paddingSize) { | 216 setPaddingSize(paddingSize) { |
| 219 this._paddingSize = paddingSize; | 217 this._paddingSize = paddingSize; |
| 220 } | 218 } |
| 221 | 219 |
| 222 /** | 220 /** |
| 223 * @param {!Event} event | 221 * @param {!Event} event |
| 224 */ | 222 */ |
| 225 _treeKeyDown(event) { | 223 _treeKeyDown(event) { |
| 226 if (event.target !== this.contentElement) | 224 if (!this.selectedTreeElement || event.target !== this.selectedTreeElement.l
istItemElement || event.shiftKey || |
| 227 return; | 225 event.metaKey || event.ctrlKey) |
| 228 | |
| 229 if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ct
rlKey) | |
| 230 return; | 226 return; |
| 231 | 227 |
| 232 var handled = false; | 228 var handled = false; |
| 233 if (event.key === 'ArrowUp' && !event.altKey) { | 229 if (event.key === 'ArrowUp' && !event.altKey) { |
| 234 handled = this.selectPrevious(); | 230 handled = this.selectPrevious(); |
| 235 } else if (event.key === 'ArrowDown' && !event.altKey) { | 231 } else if (event.key === 'ArrowDown' && !event.altKey) { |
| 236 handled = this.selectNext(); | 232 handled = this.selectNext(); |
| 237 } else if (event.key === 'ArrowLeft') { | 233 } else if (event.key === 'ArrowLeft') { |
| 238 handled = this.selectedTreeElement.collapseOrAscend(event.altKey); | 234 handled = this.selectedTreeElement.collapseOrAscend(event.altKey); |
| 239 } else if (event.key === 'ArrowRight') { | 235 } else if (event.key === 'ArrowRight') { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 /** | 318 /** |
| 323 * @param {(string|!Node)=} title | 319 * @param {(string|!Node)=} title |
| 324 * @param {boolean=} expandable | 320 * @param {boolean=} expandable |
| 325 */ | 321 */ |
| 326 constructor(title, expandable) { | 322 constructor(title, expandable) { |
| 327 /** @type {?UI.TreeOutline} */ | 323 /** @type {?UI.TreeOutline} */ |
| 328 this.treeOutline = null; | 324 this.treeOutline = null; |
| 329 this.parent = null; | 325 this.parent = null; |
| 330 this.previousSibling = null; | 326 this.previousSibling = null; |
| 331 this.nextSibling = null; | 327 this.nextSibling = null; |
| 328 this._boundOnFocus = this._onFocus.bind(this); |
| 329 this._boundOnBlur = this._onBlur.bind(this); |
| 332 | 330 |
| 333 this._listItemNode = createElement('li'); | 331 this._listItemNode = createElement('li'); |
| 334 this._titleElement = this._listItemNode.createChild('span', 'tree-element-ti
tle'); | 332 this._titleElement = this._listItemNode.createChild('span', 'tree-element-ti
tle'); |
| 335 this._listItemNode.treeElement = this; | 333 this._listItemNode.treeElement = this; |
| 336 if (title) | 334 if (title) |
| 337 this.title = title; | 335 this.title = title; |
| 338 this._listItemNode.addEventListener('mousedown', this._handleMouseDown.bind(
this), false); | 336 this._listItemNode.addEventListener('mousedown', this._handleMouseDown.bind(
this), false); |
| 339 this._listItemNode.addEventListener('click', this._treeElementToggled.bind(t
his), false); | 337 this._listItemNode.addEventListener('click', this._treeElementToggled.bind(t
his), false); |
| 340 this._listItemNode.addEventListener('dblclick', this._handleDoubleClick.bind
(this), false); | 338 this._listItemNode.addEventListener('dblclick', this._handleDoubleClick.bind
(this), false); |
| 341 | 339 |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 this._trailingIconsElement = createElementWithClass('div', 'trailing-icons
'); | 663 this._trailingIconsElement = createElementWithClass('div', 'trailing-icons
'); |
| 666 this._trailingIconsElement.classList.add('icons-container'); | 664 this._trailingIconsElement.classList.add('icons-container'); |
| 667 this._listItemNode.appendChild(this._trailingIconsElement); | 665 this._listItemNode.appendChild(this._trailingIconsElement); |
| 668 this._ensureSelection(); | 666 this._ensureSelection(); |
| 669 } | 667 } |
| 670 this._trailingIconsElement.removeChildren(); | 668 this._trailingIconsElement.removeChildren(); |
| 671 for (var icon of icons) | 669 for (var icon of icons) |
| 672 this._trailingIconsElement.appendChild(icon); | 670 this._trailingIconsElement.appendChild(icon); |
| 673 } | 671 } |
| 674 | 672 |
| 675 /** | |
| 676 * @param {boolean} focused | |
| 677 */ | |
| 678 _setFocused(focused) { | |
| 679 this._focused = focused; | |
| 680 this._listItemNode.classList.toggle('force-white-icons', focused); | |
| 681 } | |
| 682 | 673 |
| 683 /** | 674 /** |
| 684 * @return {string} | 675 * @return {string} |
| 685 */ | 676 */ |
| 686 get tooltip() { | 677 get tooltip() { |
| 687 return this._tooltip || ''; | 678 return this._tooltip || ''; |
| 688 } | 679 } |
| 689 | 680 |
| 690 /** | 681 /** |
| 691 * @param {string} x | 682 * @param {string} x |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 | 1002 |
| 1012 if (this.treeOutline.selectedTreeElement) | 1003 if (this.treeOutline.selectedTreeElement) |
| 1013 this.treeOutline.selectedTreeElement.deselect(); | 1004 this.treeOutline.selectedTreeElement.deselect(); |
| 1014 this.treeOutline.selectedTreeElement = null; | 1005 this.treeOutline.selectedTreeElement = null; |
| 1015 | 1006 |
| 1016 if (this.treeOutline._rootElement === this) | 1007 if (this.treeOutline._rootElement === this) |
| 1017 return false; | 1008 return false; |
| 1018 | 1009 |
| 1019 this.selected = true; | 1010 this.selected = true; |
| 1020 | 1011 |
| 1021 if (!omitFocus) | 1012 this.treeOutline.selectedTreeElement = this; |
| 1022 this.treeOutline.focus(); | 1013 if (this.treeOutline._focusable) |
| 1014 this._setFocusable(true); |
| 1015 if (!omitFocus || this.treeOutline.contentElement.hasFocus()) |
| 1016 this.listItemElement.focus(); |
| 1023 | 1017 |
| 1024 // Focusing on another node may detach "this" from tree. | |
| 1025 if (!this.treeOutline) | |
| 1026 return false; | |
| 1027 this.treeOutline.selectedTreeElement = this; | |
| 1028 this._listItemNode.classList.add('selected'); | 1018 this._listItemNode.classList.add('selected'); |
| 1029 this._setFocused(this.treeOutline._focused); | |
| 1030 this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementSelec
ted, this); | 1019 this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementSelec
ted, this); |
| 1031 return this.onselect(selectedByUser); | 1020 return this.onselect(selectedByUser); |
| 1032 } | 1021 } |
| 1033 | 1022 |
| 1034 /** | 1023 /** |
| 1024 * @param {boolean} focusable |
| 1025 */ |
| 1026 _setFocusable(focusable) { |
| 1027 if (focusable) { |
| 1028 this._listItemNode.setAttribute('tabIndex', 0); |
| 1029 this._listItemNode.addEventListener('focus', this._boundOnFocus, false); |
| 1030 this._listItemNode.addEventListener('blur', this._boundOnBlur, false); |
| 1031 } else { |
| 1032 this._listItemNode.removeAttribute('tabIndex'); |
| 1033 this._listItemNode.removeEventListener('focus', this._boundOnFocus, false)
; |
| 1034 this._listItemNode.removeEventListener('blur', this._boundOnBlur, false); |
| 1035 } |
| 1036 } |
| 1037 |
| 1038 _onFocus() { |
| 1039 this._listItemNode.classList.add('force-white-icons'); |
| 1040 } |
| 1041 |
| 1042 _onBlur() { |
| 1043 this._listItemNode.classList.remove('force-white-icons'); |
| 1044 } |
| 1045 |
| 1046 /** |
| 1035 * @param {boolean=} omitFocus | 1047 * @param {boolean=} omitFocus |
| 1036 */ | 1048 */ |
| 1037 revealAndSelect(omitFocus) { | 1049 revealAndSelect(omitFocus) { |
| 1038 this.reveal(true); | 1050 this.reveal(true); |
| 1039 this.select(omitFocus); | 1051 this.select(omitFocus); |
| 1040 } | 1052 } |
| 1041 | 1053 |
| 1042 /** | 1054 deselect() { |
| 1043 * @param {boolean=} supressOnDeselect | 1055 var hadFocus = this._listItemNode.hasFocus(); |
| 1044 */ | 1056 this.selected = false; |
| 1045 deselect(supressOnDeselect) { | 1057 this._listItemNode.classList.remove('selected'); |
| 1046 if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !t
his.selected) | 1058 this._setFocusable(false); |
| 1047 return; | |
| 1048 | 1059 |
| 1049 this.selected = false; | 1060 if (this.treeOutline && this.treeOutline.selectedTreeElement === this) { |
| 1050 this.treeOutline.selectedTreeElement = null; | 1061 this.treeOutline.selectedTreeElement = null; |
| 1051 this._listItemNode.classList.remove('selected'); | 1062 if (hadFocus) |
| 1052 this._setFocused(false); | 1063 this.treeOutline.focus(); |
| 1064 } |
| 1053 } | 1065 } |
| 1054 | 1066 |
| 1055 _populateIfNeeded() { | 1067 _populateIfNeeded() { |
| 1056 if (this.treeOutline && this._expandable && !this._children) { | 1068 if (this.treeOutline && this._expandable && !this._children) { |
| 1057 this._children = []; | 1069 this._children = []; |
| 1058 this.onpopulate(); | 1070 this.onpopulate(); |
| 1059 } | 1071 } |
| 1060 } | 1072 } |
| 1061 | 1073 |
| 1062 onpopulate() { | 1074 onpopulate() { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 var paddingLeftValue = window.getComputedStyle(this._listItemNode).paddingLe
ft; | 1206 var paddingLeftValue = window.getComputedStyle(this._listItemNode).paddingLe
ft; |
| 1195 console.assert(paddingLeftValue.endsWith('px')); | 1207 console.assert(paddingLeftValue.endsWith('px')); |
| 1196 var computedLeftPadding = parseFloat(paddingLeftValue); | 1208 var computedLeftPadding = parseFloat(paddingLeftValue); |
| 1197 var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding; | 1209 var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding; |
| 1198 return event.pageX >= left && event.pageX <= left + UI.TreeElement._ArrowTog
gleWidth && this._expandable; | 1210 return event.pageX >= left && event.pageX <= left + UI.TreeElement._ArrowTog
gleWidth && this._expandable; |
| 1199 } | 1211 } |
| 1200 }; | 1212 }; |
| 1201 | 1213 |
| 1202 /** @const */ | 1214 /** @const */ |
| 1203 UI.TreeElement._ArrowToggleWidth = 10; | 1215 UI.TreeElement._ArrowToggleWidth = 10; |
| OLD | NEW |