Changeset 51339 in webkit
- Timestamp:
- Nov 24, 2009 9:15:01 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/inspector/timeline-test.js
r51296 r51339 119 119 function frontend_getTimelineResults() { 120 120 var result = []; 121 var records = WebInspector.panels.timeline._records; 122 for (var i = 0; i < records.length; ++i) { 123 result.push(records[i].record); 121 function addRecords(records) 122 { 123 if (!records) 124 return; 125 for (var i = 0; i < records.length; ++i) { 126 result.push(records[i].record); 127 addRecords(records[i].children); 128 } 124 129 } 130 addRecords(WebInspector.panels.timeline._records); 125 131 return result; 126 132 } -
trunk/WebCore/ChangeLog
r51337 r51339 1 2009-11-23 Pavel Feldman <pfeldman@chromium.org> 2 3 Reviewed by Timothy Hatcher. 4 5 Web Inspector: Implement expandable compartments on timeline panel. 6 7 https://bugs.webkit.org/show_bug.cgi?id=31796 8 9 * inspector/front-end/TimelineOverviewPane.js: 10 (WebInspector.TimelineOverviewPane.prototype._setWindowPosition): 11 * inspector/front-end/TimelinePanel.js: 12 (WebInspector.TimelinePanel): 13 (WebInspector.TimelinePanel.prototype.addRecordToTimeline): 14 (WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline): 15 (WebInspector.TimelinePanel.prototype._formatRecord): 16 (WebInspector.TimelinePanel.prototype._refreshRecords): 17 (WebInspector.TimelinePanel.prototype._addToRecordsWindow): 18 (WebInspector.TimelineRecordListRow): 19 (WebInspector.TimelineRecordListRow.prototype.update): 20 (WebInspector.TimelineRecordListRow.prototype.dispose): 21 (WebInspector.TimelineRecordGraphRow): 22 (WebInspector.TimelineRecordGraphRow.prototype.update): 23 (WebInspector.TimelineRecordGraphRow.prototype._onClick): 24 (WebInspector.TimelineRecordGraphRow.prototype.dispose): 25 * inspector/front-end/inspector.css: 26 1 27 2009-11-24 Mark Rowe <mrowe@apple.com> 2 28 -
trunk/WebCore/inspector/front-end/TimelineGrid.js
r51296 r51339 56 56 }, 57 57 58 updateDividers: function(force, calculator )58 updateDividers: function(force, calculator, paddingLeft) 59 59 { 60 60 var dividerCount = Math.round(this._dividersElement.offsetWidth / 64); … … 63 63 return false; 64 64 65 if (!(typeof paddingLeft === "number")) 66 paddingLeft = 0; 65 67 this._currentDividerSlice = slice; 66 68 67 this._dividersElement.removeChildren();68 69 this._eventDividersElement.removeChildren(); 69 this._dividersLabelBarElement.removeChildren(); 70 // Reuse divider elements and labels. 71 var divider = this._dividersElement.firstChild; 72 var dividerLabelBar = this._dividersLabelBarElement.firstChild; 70 73 71 for (var i = 1; i <= dividerCount; ++i) { 72 var divider = document.createElement("div"); 73 divider.className = "resources-divider"; 74 var clientWidth = this._dividersLabelBarElement.clientWidth - paddingLeft; 75 for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) { 76 if (!divider) { 77 divider = document.createElement("div"); 78 divider.className = "resources-divider"; 79 this._dividersElement.appendChild(divider); 80 81 dividerLabelBar = document.createElement("div"); 82 dividerLabelBar.className = "resources-divider"; 83 var label = document.createElement("div"); 84 label.className = "resources-divider-label"; 85 dividerLabelBar._labelElement = label; 86 dividerLabelBar.appendChild(label); 87 this._dividersLabelBarElement.appendChild(dividerLabelBar); 88 } 89 74 90 if (i === dividerCount) 75 91 divider.addStyleClass("last"); 76 divider.style.left = ((i / dividerCount) * 100) + "%"; 92 else 93 divider.removeStyleClass("last"); 77 94 78 this._dividersElement.appendChild(divider.cloneNode()); 95 var left = paddingLeft + clientWidth * (i / dividerCount); 96 var percentLeft = 100 * left / this._dividersLabelBarElement.clientWidth + "%"; 97 divider.style.left = percentLeft; 98 dividerLabelBar.style.left = percentLeft; 79 99 80 var label = document.createElement("div");81 label.className = "resources-divider-label";82 100 if (!isNaN(slice)) 83 label.textContent = calculator.formatValue(slice * i); 84 divider.appendChild(label); 101 dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i); 85 102 86 this._dividersLabelBarElement.appendChild(divider); 103 divider = divider.nextSibling; 104 dividerLabelBar = dividerLabelBar.nextSibling; 105 } 106 107 // Remove extras. 108 while (divider) { 109 var nextDivider = divider.nextSibling; 110 this._dividersElement.removeChild(divider); 111 divider = nextDivider; 112 } 113 while (dividerLabelBar) { 114 var nextDivider = dividerLabelBar.nextSibling; 115 this._dividersLabelBarElement.removeChild(dividerLabelBar); 116 dividerLabelBar = nextDivider; 87 117 } 88 118 return true; -
trunk/WebCore/inspector/front-end/TimelineOverviewPane.js
r51296 r51339 113 113 } 114 114 115 function forAllRecords(recordsArray, callback) 116 { 117 if (!recordsArray) 118 return; 119 for (var i = 0; i < recordsArray.length; ++i) { 120 callback(recordsArray[i]); 121 forAllRecords(recordsArray[i].children, callback); 122 } 123 } 124 115 125 // Create sparse arrays with 101 cells each to fill with chunks for a given category. 116 126 this._overviewCalculator.reset(); 117 118 for (var i = 1; i < records.length; ++i) 119 this._overviewCalculator.updateBoundaries(records[i]); 120 121 for (var i = 0; i < records.length; ++i) { 122 var record = records[i]; 127 forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator)); 128 129 function markTimeline(record) 130 { 123 131 var percentages = this._overviewCalculator.computeBarGraphPercentages(record); 124 132 125 133 var end = Math.round(percentages.end); 126 134 var categoryName = record.category.name; … … 128 136 timelines[categoryName][j] = true; 129 137 } 138 forAllRecords(records, markTimeline.bind(this)); 130 139 131 140 // Convert sparse arrays to continuous segments, render graphs for each. … … 231 240 { 232 241 if (typeof start === "number") { 233 if (start > this._rightResizeElement.offsetLeft - 25)234 start = this._rightResizeElement.offsetLeft - 25;242 if (start > this._rightResizeElement.offsetLeft - 4) 243 start = this._rightResizeElement.offsetLeft - 4; 235 244 236 245 this.windowLeft = start / this._overviewGrid.element.clientWidth; … … 239 248 } 240 249 if (typeof end === "number") { 241 if (end < this._leftResizeElement.offsetLeft + 30)242 end = this._leftResizeElement.offsetLeft + 30;250 if (end < this._leftResizeElement.offsetLeft + 12) 251 end = this._leftResizeElement.offsetLeft + 12; 243 252 244 253 this.windowRight = end / this._overviewGrid.element.clientWidth; -
trunk/WebCore/inspector/front-end/TimelinePanel.js
r51297 r51339 61 61 62 62 this._timelineGrid = new WebInspector.TimelineGrid(); 63 varitemsGraphsElement = this._timelineGrid.itemsGraphsElement;64 itemsGraphsElement.id = "timeline-graphs";63 this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement; 64 this._itemsGraphsElement.id = "timeline-graphs"; 65 65 this._containerContentElement.appendChild(this._timelineGrid.element); 66 66 67 67 this._topGapElement = document.createElement("div"); 68 68 this._topGapElement.className = "timeline-gap"; 69 itemsGraphsElement.appendChild(this._topGapElement);69 this._itemsGraphsElement.appendChild(this._topGapElement); 70 70 71 71 this._graphRowsElement = document.createElement("div"); 72 itemsGraphsElement.appendChild(this._graphRowsElement);72 this._itemsGraphsElement.appendChild(this._graphRowsElement); 73 73 74 74 this._bottomGapElement = document.createElement("div"); 75 75 this._bottomGapElement.className = "timeline-gap"; 76 itemsGraphsElement.appendChild(this._bottomGapElement);76 this._itemsGraphsElement.appendChild(this._bottomGapElement); 77 77 78 78 this._createStatusbarButtons(); … … 137 137 addRecordToTimeline: function(record) 138 138 { 139 this._innerAddRecordToTimeline(record, this._records); 140 this._scheduleRefresh(); 141 }, 142 143 _innerAddRecordToTimeline: function(record, collection) 144 { 139 145 var formattedRecord = this._formatRecord(record); 146 140 147 // Glue subsequent records with same category and title together if they are closer than 100ms to each other. 141 148 if (this._lastRecord && (!record.children || !record.children.length) && … … 147 154 this._lastRecord.count++; 148 155 } else { 149 this._records.push(formattedRecord); 150 151 for (var i = 0; record.children && i < record.children.length; ++i) 152 this.addRecordToTimeline(record.children[i]); 156 collection.push(formattedRecord); 157 for (var i = 0; record.children && i < record.children.length; ++i) { 158 if (!formattedRecord.children) 159 formattedRecord.children = []; 160 var formattedChild = this._innerAddRecordToTimeline(record.children[i], formattedRecord.children); 161 formattedChild.parent = formattedRecord; 162 } 153 163 this._lastRecord = record.children && record.children.length ? null : formattedRecord; 154 164 } 155 this._scheduleRefresh();165 return formattedRecord; 156 166 }, 157 167 … … 197 207 } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse) { 198 208 var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; 199 sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime; 200 formattedRecord.startTime = sendRequestRecord.startTime; 201 sendRequestRecord.details = this._getRecordDetails(record); 209 if (sendRequestRecord) { // False if we started instrumentation in the middle of request. 210 sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime; 211 formattedRecord.startTime = sendRequestRecord.startTime; 212 sendRequestRecord.details = this._getRecordDetails(record); 213 } 202 214 } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceFinish) { 203 215 var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; … … 315 327 var percentages = this._calculator.computeBarGraphPercentages(record); 316 328 if (percentages.start < 100 && percentages.end >= 0 && !record.category.hidden) 317 recordsInWindow.push(record);329 this._addToRecordsWindow(record, recordsInWindow); 318 330 } 319 331 … … 321 333 var visibleTop = this._containerElement.scrollTop; 322 334 var visibleBottom = visibleTop + this._containerElement.clientHeight; 335 336 // Define row height, should be in sync with styles for timeline graphs. 323 337 const rowHeight = 18; 324 325 // Convert visible area to visible indexes. 338 const expandOffset = 15; 339 340 // Convert visible area to visible indexes. Always include top-level record for a visible nested record. 326 341 var startIndex = Math.max(0, Math.floor(visibleTop / rowHeight) - 1); 342 while (startIndex > 0 && recordsInWindow[startIndex].parent) 343 startIndex--; 327 344 var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight)); 328 345 while (endIndex < recordsInWindow.length - 1 && recordsInWindow[startIndex].parent) 346 endIndex++; 347 348 // Resize gaps first. 349 const top = (startIndex * rowHeight) + "px"; 350 this._topGapElement.style.height = top; 351 this.sidebarElement.style.top = top; 352 this.sidebarResizeElement.style.top = top; 353 this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px"; 354 355 // Update visible rows. 329 356 var listRowElement = this._sidebarListElement.firstChild; 330 357 var graphRowElement = this._graphRowsElement.firstChild; 358 var width = this._graphRowsElement.offsetWidth; 359 var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true); 331 360 for (var i = startIndex; i < endIndex; ++i) { 332 361 var record = recordsInWindow[i]; … … 338 367 } 339 368 if (!graphRowElement) { 340 graphRowElement = new WebInspector.TimelineRecordGraphRow( ).element;369 graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element; 341 370 this._graphRowsElement.appendChild(graphRowElement); 342 371 } 343 372 344 373 listRowElement.listRow.update(record, isEven); 345 graphRowElement.graphRow.update(record, isEven, this._calculator );374 graphRowElement.graphRow.update(record, isEven, this._calculator, width, expandOffset); 346 375 347 376 listRowElement = listRowElement.nextSibling; … … 349 378 } 350 379 380 // Remove extra rows. 351 381 while (listRowElement) { 352 382 var nextElement = listRowElement.nextSibling; 353 listRowElement. parentElement.removeChild(listRowElement);383 listRowElement.listRow.dispose(); 354 384 listRowElement = nextElement; 355 385 } 356 357 386 while (graphRowElement) { 358 387 var nextElement = graphRowElement.nextSibling; 359 graphRowElement. parentElement.removeChild(graphRowElement);388 graphRowElement.graphRow.dispose(); 360 389 graphRowElement = nextElement; 361 390 } 362 391 363 this._timelineGrid.updateDividers(true, this._calculator); 364 365 const top = (startIndex * rowHeight) + "px"; 366 this._topGapElement.style.height = top; 367 this.sidebarElement.style.top = top; 368 this.sidebarResizeElement.style.top = top; 369 this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px"; 392 // Reserve some room for expand / collapse controls to the left for records that start at 0ms. 393 var timelinePaddingLeft = this._calculator.windowLeft === 0 ? expandOffset : 0; 394 this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft); 370 395 this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight); 396 }, 397 398 _addToRecordsWindow: function(record, recordsWindow) 399 { 400 recordsWindow.push(record); 401 if (!record.collapsed) { 402 var index = recordsWindow.length; 403 for (var i = 0; record.children && i < record.children.length; ++i) 404 this._addToRecordsWindow(record.children[i], recordsWindow); 405 record.visibleChildrenCount = recordsWindow.length - index; 406 } 371 407 }, 372 408 … … 475 511 this.element = document.createElement("div"); 476 512 this.element.listRow = this; 477 478 513 var iconElement = document.createElement("span"); 479 514 iconElement.className = "timeline-tree-icon"; … … 517 552 else 518 553 this._repeatCountElement.textContent = ""; 554 }, 555 556 dispose: function() 557 { 558 this.element.parentElement.removeChild(this.element); 519 559 } 520 560 } 521 561 522 562 523 WebInspector.TimelineRecordGraphRow = function( )563 WebInspector.TimelineRecordGraphRow = function(graphContainer, refreshCallback, rowHeight) 524 564 { 525 565 this.element = document.createElement("div"); … … 533 573 this._barElement.className = "timeline-graph-bar"; 534 574 this._barAreaElement.appendChild(this._barElement); 575 576 this._expandElement = document.createElement("div"); 577 this._expandElement.className = "timeline-expandable"; 578 graphContainer.appendChild(this._expandElement); 579 580 var leftBorder = document.createElement("div"); 581 leftBorder.className = "timeline-expandable-left"; 582 this._expandElement.appendChild(leftBorder); 583 584 this._expandElement.addEventListener("click", this._onClick.bind(this)); 585 this._refreshCallback = refreshCallback; 586 this._rowHeight = rowHeight; 535 587 } 536 588 537 589 WebInspector.TimelineRecordGraphRow.prototype = { 538 update: function(record, isEven, calculator) 539 { 590 update: function(record, isEven, calculator, clientWidth, expandOffset) 591 { 592 this._record = record; 540 593 this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : ""); 541 594 var percentages = calculator.computeBarGraphPercentages(record); 542 this._barElement.style.setProperty("left", percentages.start + "%"); 543 this._barElement.style.setProperty("right", (100 - percentages.end) + "%"); 595 var left = percentages.start / 100 * clientWidth; 596 var width = (percentages.end - percentages.start) / 100 * clientWidth; 597 this._barElement.style.left = (left + expandOffset) + "px"; 598 this._barElement.style.width = width + "px"; 599 600 if (record.visibleChildrenCount) { 601 this._expandElement.style.top = this.element.offsetTop + "px"; 602 this._expandElement.style.left = left + "px"; 603 this._expandElement.style.width = Math.max(12, width + 25) + "px"; 604 if (!record.collapsed) { 605 this._expandElement.style.height = (record.visibleChildrenCount + 1) * this._rowHeight + "px"; 606 this._expandElement.addStyleClass("timeline-expandable-expanded"); 607 this._expandElement.removeStyleClass("timeline-expandable-collapsed"); 608 } else { 609 this._expandElement.style.height = this._rowHeight + "px"; 610 this._expandElement.addStyleClass("timeline-expandable-collapsed"); 611 this._expandElement.removeStyleClass("timeline-expandable-expanded"); 612 } 613 this._expandElement.removeStyleClass("hidden"); 614 } else { 615 this._expandElement.addStyleClass("hidden"); 616 } 617 }, 618 619 _onClick: function(event) 620 { 621 this._record.collapsed = !this._record.collapsed; 622 this._refreshCallback(); 623 }, 624 625 dispose: function() 626 { 627 this.element.parentElement.removeChild(this.element); 628 this._expandElement.parentElement.removeChild(this._expandElement); 544 629 } 545 630 } -
trunk/WebCore/inspector/front-end/inspector.css
r51297 r51339 3289 3289 } 3290 3290 3291 .timeline .sidebar { 3292 overflow-y: hidden; 3293 z-index: 100; 3294 } 3295 3291 3296 #timeline-overview-separator { 3292 3297 position: absolute; … … 3412 3417 height: 18px; 3413 3418 line-height: 15px; 3419 padding-right: 5px; 3414 3420 padding-left: 10px; 3415 3421 padding-top: 2px; … … 3417 3423 text-overflow: ellipsis; 3418 3424 overflow: hidden; 3425 } 3426 3427 .timeline-expandable { 3428 position: absolute; 3429 border-left: 1px solid rgb(163, 163, 163); 3430 } 3431 3432 .timeline-expandable-left { 3433 position: absolute; 3434 top: 0; 3435 bottom: 0; 3436 left: 0; 3437 width: 3px; 3438 border-top: 1px solid rgb(163, 163, 163); 3439 border-bottom: 1px solid rgb(163, 163, 163); 3440 } 3441 3442 .timeline-expandable-collapsed { 3443 background-image: url(Images/disclosureTriangleSmallRightBlack.png); 3444 background-position-x: 1px; 3445 background-position-y: 2px; 3446 background-repeat: no-repeat; 3447 } 3448 3449 .timeline-expandable-expanded { 3450 background-image: url(Images/disclosureTriangleSmallDownBlack.png); 3451 background-position-x: 1px; 3452 background-position-y: 3px; 3453 background-repeat: no-repeat; 3419 3454 } 3420 3455 … … 3485 3520 top: 0; 3486 3521 bottom: 0; 3487 right: 8px;3488 left: 9px;3522 right: 0; 3523 left: 3px; 3489 3524 pointer-events: none; 3490 3525 } -
trunk/WebCore/inspector/front-end/utilities.js
r50909 r51339 551 551 formatterFunction = String.sprintf; 552 552 553 if (seconds === 0) 554 return "0"; 555 553 556 var ms = seconds * 1000; 554 557 if (higherResolution && ms < 1000)
Note: See TracChangeset
for help on using the changeset viewer.