diff options
| author | Steve Block <steveblock@google.com> | 2009-12-17 09:55:06 -0800 |
|---|---|---|
| committer | Android Git Automerger <android-git-automerger@android.com> | 2009-12-17 09:55:06 -0800 |
| commit | b880d713c04257ca40abfef97c300afdead423b8 (patch) | |
| tree | 6982576c228bcd1a7efe98afed544d840751094c /WebCore/inspector/front-end/TimelinePanel.js | |
| parent | e2e7a5c57b53f01e63a0245b4420d54b454cb373 (diff) | |
| parent | 643ca7872b450ea4efacab6188849e5aac2ba161 (diff) | |
| download | external_webkit-b880d713c04257ca40abfef97c300afdead423b8.zip external_webkit-b880d713c04257ca40abfef97c300afdead423b8.tar.gz external_webkit-b880d713c04257ca40abfef97c300afdead423b8.tar.bz2 | |
am 643ca787: Merge webkit.org at r51976 : Initial merge by git.
Merge commit '643ca7872b450ea4efacab6188849e5aac2ba161' into eclair-mr2-plus-aosp
* commit '643ca7872b450ea4efacab6188849e5aac2ba161':
Merge webkit.org at r51976 : Initial merge by git.
Diffstat (limited to 'WebCore/inspector/front-end/TimelinePanel.js')
| -rw-r--r-- | WebCore/inspector/front-end/TimelinePanel.js | 554 |
1 files changed, 411 insertions, 143 deletions
diff --git a/WebCore/inspector/front-end/TimelinePanel.js b/WebCore/inspector/front-end/TimelinePanel.js index df63a0b..ac36fa5 100644 --- a/WebCore/inspector/front-end/TimelinePanel.js +++ b/WebCore/inspector/front-end/TimelinePanel.js @@ -30,19 +30,56 @@ WebInspector.TimelinePanel = function() { - WebInspector.AbstractTimelinePanel.call(this); - + WebInspector.Panel.call(this); this.element.addStyleClass("timeline"); - this.createInterface(); - this.summaryBar.element.id = "timeline-summary"; - this.itemsGraphsElement.id = "timeline-graphs"; + this._overviewPane = new WebInspector.TimelineOverviewPane(this.categories); + this._overviewPane.addEventListener("window changed", this._scheduleRefresh, this); + this._overviewPane.addEventListener("filter changed", this._refresh, this); + this.element.appendChild(this._overviewPane.element); - this._createStatusbarButtons(); + this._sidebarBackgroundElement = document.createElement("div"); + this._sidebarBackgroundElement.className = "sidebar timeline-sidebar-background"; + this.element.appendChild(this._sidebarBackgroundElement); + + this._containerElement = document.createElement("div"); + this._containerElement.id = "timeline-container"; + this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false); + this.element.appendChild(this._containerElement); + + this.createSidebar(this._containerElement, this._containerElement); + var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true); + itemsTreeElement.expanded = true; + this.sidebarTree.appendChild(itemsTreeElement); + + this._sidebarListElement = document.createElement("div"); + this.sidebarElement.appendChild(this._sidebarListElement); + + this._containerContentElement = document.createElement("div"); + this._containerContentElement.id = "resources-container-content"; + this._containerElement.appendChild(this._containerContentElement); + + this._timelineGrid = new WebInspector.TimelineGrid(); + this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement; + this._itemsGraphsElement.id = "timeline-graphs"; + this._containerContentElement.appendChild(this._timelineGrid.element); + + this._topGapElement = document.createElement("div"); + this._topGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._topGapElement); - this.calculator = new WebInspector.TimelineCalculator(); + this._graphRowsElement = document.createElement("div"); + this._itemsGraphsElement.appendChild(this._graphRowsElement); - this.filter(this.filterAllElement, false); + this._bottomGapElement = document.createElement("div"); + this._bottomGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._bottomGapElement); + + this._createStatusbarButtons(); + + this._records = []; + this._sendRequestRecords = {}; + this._calculator = new WebInspector.TimelineCalculator(); } WebInspector.TimelinePanel.prototype = { @@ -64,20 +101,12 @@ WebInspector.TimelinePanel.prototype = { this._categories = { loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), "rgb(47,102,236)"), scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), "rgb(157,231,119)"), - rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)"), - other: new WebInspector.TimelineCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)") + rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)") }; } return this._categories; }, - populateSidebar: function() - { - this.itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true); - this.itemsTreeElement.expanded = true; - this.sidebarTree.appendChild(this.itemsTreeElement); - }, - _createStatusbarButtons: function() { this.toggleTimelineButton = new WebInspector.StatusBarButton("", "record-profile-status-bar-item"); @@ -87,6 +116,14 @@ WebInspector.TimelinePanel.prototype = { this.clearButton.addEventListener("click", this.reset.bind(this), false); }, + _toggleTimelineButtonClicked: function() + { + if (this.toggleTimelineButton.toggled) + InspectorBackend.stopTimelineProfiler(); + else + InspectorBackend.startTimelineProfiler(); + }, + timelineWasStarted: function() { this.toggleTimelineButton.toggled = true; @@ -99,7 +136,14 @@ WebInspector.TimelinePanel.prototype = { addRecordToTimeline: function(record) { + this._innerAddRecordToTimeline(record, this._records); + this._scheduleRefresh(); + }, + + _innerAddRecordToTimeline: function(record, collection) + { var formattedRecord = this._formatRecord(record); + // Glue subsequent records with same category and title together if they are closer than 100ms to each other. if (this._lastRecord && (!record.children || !record.children.length) && this._lastRecord.category == formattedRecord.category && @@ -108,40 +152,25 @@ WebInspector.TimelinePanel.prototype = { formattedRecord.startTime - this._lastRecord.endTime < 0.1) { this._lastRecord.endTime = formattedRecord.endTime; this._lastRecord.count++; - this.refreshItem(this._lastRecord); } else { - this.addItem(formattedRecord); - - for (var i = 0; record.children && i < record.children.length; ++i) - this.addRecordToTimeline(record.children[i]); + collection.push(formattedRecord); + for (var i = 0; record.children && i < record.children.length; ++i) { + if (!formattedRecord.children) + formattedRecord.children = []; + var formattedChild = this._innerAddRecordToTimeline(record.children[i], formattedRecord.children); + formattedChild.parent = formattedRecord; + } this._lastRecord = record.children && record.children.length ? null : formattedRecord; } - }, - - createItemTreeElement: function(item) - { - return new WebInspector.TimelineRecordTreeElement(item); - }, - - createItemGraph: function(item) - { - return new WebInspector.TimelineGraph(item); - }, - - _toggleTimelineButtonClicked: function() - { - if (InspectorController.timelineProfilerEnabled()) - InspectorController.stopTimelineProfiler(); - else - InspectorController.startTimelineProfiler(); + return formattedRecord; }, _formatRecord: function(record) { + var recordTypes = WebInspector.TimelineAgent.RecordType; if (!this._recordStyles) { this._recordStyles = {}; - var recordTypes = WebInspector.TimelineAgent.RecordType; - this._recordStyles[recordTypes.DOMDispatch] = { title: WebInspector.UIString("DOM Event"), category: this.categories.scripting }; + this._recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: this.categories.scripting }; this._recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: this.categories.rendering }; this._recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: this.categories.rendering }; this._recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: this.categories.rendering }; @@ -151,13 +180,16 @@ WebInspector.TimelinePanel.prototype = { this._recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: this.categories.scripting }; this._recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: this.categories.scripting }; this._recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: this.categories.scripting }; - this._recordStyles[recordTypes.EvaluateScriptTag] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting }; - this._recordStyles["Other"] = { title: WebInspector.UIString("Other"), icon: 0, category: this.categories.other }; + this._recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting }; + this._recordStyles[recordTypes.MarkTimeline] = { title: WebInspector.UIString("Mark"), category: this.categories.scripting }; + this._recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: this.categories.loading }; + this._recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: this.categories.loading }; + this._recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: this.categories.loading }; } var style = this._recordStyles[record.type]; if (!style) - style = this._recordStyles["Other"]; + style = this._recordStyles[recordTypes.EventDispatch]; var formattedRecord = {}; formattedRecord.category = style.category; @@ -166,119 +198,278 @@ WebInspector.TimelinePanel.prototype = { formattedRecord.data = record.data; formattedRecord.count = 1; formattedRecord.type = record.type; - formattedRecord.details = this._getRecordDetails(record); formattedRecord.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : formattedRecord.startTime; + formattedRecord.record = record; + + // Make resource receive record last since request was sent; make finish record last since response received. + if (record.type === WebInspector.TimelineAgent.RecordType.ResourceSendRequest) { + this._sendRequestRecords[record.data.identifier] = formattedRecord; + } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse) { + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + if (sendRequestRecord) { // False if we started instrumentation in the middle of request. + sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime; + formattedRecord.startTime = sendRequestRecord.startTime; + sendRequestRecord.details = this._getRecordDetails(record); + } + } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceFinish) { + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + if (sendRequestRecord) // False for main resource. + formattedRecord.startTime = sendRequestRecord._responseReceivedFormattedTime; + } + formattedRecord.details = this._getRecordDetails(record); + return formattedRecord; }, - + _getRecordDetails: function(record) { switch (record.type) { - case WebInspector.TimelineAgent.RecordType.DOMDispatch: - return record.data.type; + case WebInspector.TimelineAgent.RecordType.EventDispatch: + return record.data ? record.data.type : ""; + case WebInspector.TimelineAgent.RecordType.Paint: + return record.data.width + "\u2009\u00d7\u2009" + record.data.height; case WebInspector.TimelineAgent.RecordType.TimerInstall: case WebInspector.TimelineAgent.RecordType.TimerRemove: case WebInspector.TimelineAgent.RecordType.TimerFire: return record.data.timerId; case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange: case WebInspector.TimelineAgent.RecordType.XHRLoad: - case WebInspector.TimelineAgent.RecordType.EvaluateScriptTag: - return record.data.url; + case WebInspector.TimelineAgent.RecordType.EvaluateScript: + case WebInspector.TimelineAgent.RecordType.ResourceSendRequest: + return WebInspector.displayNameForURL(record.data.url); + case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse: + case WebInspector.TimelineAgent.RecordType.ResourceFinish: + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + return sendRequestRecord ? WebInspector.displayNameForURL(sendRequestRecord.data.url) : ""; + case WebInspector.TimelineAgent.RecordType.MarkTimeline: + return record.data.message; default: return ""; } }, + setSidebarWidth: function(width) + { + WebInspector.Panel.prototype.setSidebarWidth.call(this, width); + this._sidebarBackgroundElement.style.width = width + "px"; + this._overviewPane.setSidebarWidth(width); + }, + + updateMainViewWidth: function(width) + { + this._containerContentElement.style.left = width + "px"; + this._scheduleRefresh(); + this._overviewPane.updateMainViewWidth(width); + }, + + resize: function() { + this._scheduleRefresh(); + }, + reset: function() { - WebInspector.AbstractTimelinePanel.prototype.reset.call(this); this._lastRecord = null; - } -} + this._sendRequestRecords = {}; + this._overviewPane.reset(); + this._records = []; + this._refresh(); + }, -WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.AbstractTimelinePanel.prototype; + show: function() + { + WebInspector.Panel.prototype.show.call(this); + if (this._needsRefresh) + this._refresh(); + }, -WebInspector.TimelineCategory = function(name, title, color) -{ - WebInspector.AbstractTimelineCategory.call(this, name, title, color); -} + _onScroll: function(event) + { + var scrollTop = this._containerElement.scrollTop; + var dividersTop = Math.max(0, scrollTop); + this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop); + this._scheduleRefresh(true); + }, -WebInspector.TimelineCategory.prototype = { -} + _scheduleRefresh: function(immediate) + { + if (this._needsRefresh) + return; + this._needsRefresh = true; + + if (this.visible && !("_refreshTimeout" in this)) + this._refreshTimeout = setTimeout(this._refresh.bind(this), immediate ? 0 : 100); + }, -WebInspector.TimelineCategory.prototype.__proto__ = WebInspector.AbstractTimelineCategory.prototype; + _refresh: function() + { + this._needsRefresh = false; + if ("_refreshTimeout" in this) { + clearTimeout(this._refreshTimeout); + delete this._refreshTimeout; + } + this._overviewPane.update(this._records); + this._refreshRecords(); + }, + _refreshRecords: function() + { + this._calculator.windowLeft = this._overviewPane.windowLeft; + this._calculator.windowRight = this._overviewPane.windowRight; + this._calculator.reset(); + + for (var i = 0; i < this._records.length; ++i) + this._calculator.updateBoundaries(this._records[i]); + + var recordsInWindow = []; + for (var i = 0; i < this._records.length; ++i) { + var record = this._records[i]; + var percentages = this._calculator.computeBarGraphPercentages(record); + if (percentages.start < 100 && percentages.end >= 0 && !record.category.hidden) + this._addToRecordsWindow(record, recordsInWindow); + } -WebInspector.TimelineRecordTreeElement = function(record) -{ - this._record = record; + // Calculate the visible area. + var visibleTop = this._containerElement.scrollTop; + var visibleBottom = visibleTop + this._containerElement.clientHeight; + + // Define row height, should be in sync with styles for timeline graphs. + const rowHeight = 18; + const expandOffset = 15; + + // Convert visible area to visible indexes. Always include top-level record for a visible nested record. + var startIndex = Math.max(0, Math.floor(visibleTop / rowHeight) - 1); + while (startIndex > 0 && recordsInWindow[startIndex].parent) + startIndex--; + var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight)); + while (endIndex < recordsInWindow.length - 1 && recordsInWindow[startIndex].parent) + endIndex++; + + // Resize gaps first. + const top = (startIndex * rowHeight) + "px"; + this._topGapElement.style.height = top; + this.sidebarElement.style.top = top; + this.sidebarResizeElement.style.top = top; + this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px"; + + // Update visible rows. + var listRowElement = this._sidebarListElement.firstChild; + var graphRowElement = this._graphRowsElement.firstChild; + var width = this._graphRowsElement.offsetWidth; + var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true); + for (var i = startIndex; i < endIndex; ++i) { + var record = recordsInWindow[i]; + var isEven = !(i % 2); + + if (!listRowElement) { + listRowElement = new WebInspector.TimelineRecordListRow().element; + this._sidebarListElement.appendChild(listRowElement); + } + if (!graphRowElement) { + graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element; + this._graphRowsElement.appendChild(graphRowElement); + } + + listRowElement.listRow.update(record, isEven); + graphRowElement.graphRow.update(record, isEven, this._calculator, width, expandOffset); + + listRowElement = listRowElement.nextSibling; + graphRowElement = graphRowElement.nextSibling; + } - // Pass an empty title, the title gets made later in onattach. - TreeElement.call(this, "", null, false); -} + // Remove extra rows. + while (listRowElement) { + var nextElement = listRowElement.nextSibling; + listRowElement.listRow.dispose(); + listRowElement = nextElement; + } + while (graphRowElement) { + var nextElement = graphRowElement.nextSibling; + graphRowElement.graphRow.dispose(); + graphRowElement = nextElement; + } + + // Reserve some room for expand / collapse controls to the left for records that start at 0ms. + var timelinePaddingLeft = this._calculator.windowLeft === 0 ? expandOffset : 0; + this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft); + this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight); + }, -WebInspector.TimelineRecordTreeElement.prototype = { - onattach: function() - { - this.listItemElement.removeChildren(); - this.listItemElement.addStyleClass("timeline-tree-item"); - this.listItemElement.addStyleClass("timeline-category-" + this._record.category.name); - - var iconElement = document.createElement("span"); - iconElement.className = "timeline-tree-icon"; - this.listItemElement.appendChild(iconElement); - - this.typeElement = document.createElement("span"); - this.typeElement.className = "type"; - this.typeElement.textContent = this._record.title; - this.listItemElement.appendChild(this.typeElement); - - if (this._record.details) { - var separatorElement = document.createElement("span"); - separatorElement.className = "separator"; - separatorElement.textContent = " "; - - var dataElement = document.createElement("span"); - dataElement.className = "data"; - dataElement.textContent = "(" + this._record.details + ")"; - dataElement.addStyleClass("dimmed"); - this.listItemElement.appendChild(separatorElement); - this.listItemElement.appendChild(dataElement); + _addToRecordsWindow: function(record, recordsWindow) + { + recordsWindow.push(record); + if (!record.collapsed) { + var index = recordsWindow.length; + for (var i = 0; record.children && i < record.children.length; ++i) + this._addToRecordsWindow(record.children[i], recordsWindow); + record.visibleChildrenCount = recordsWindow.length - index; } }, - refresh: function() + _adjustScrollPosition: function(totalHeight) { - if (this._record.count > 1) - this.typeElement.textContent = this._record.title + " x " + this._record.count; + // Prevent the container from being scrolled off the end. + if ((this._containerElement.scrollTop + this._containerElement.offsetHeight) > totalHeight + 1) + this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight); } } -WebInspector.TimelineRecordTreeElement.prototype.__proto__ = TreeElement.prototype; +WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype; + + +WebInspector.TimelineCategory = function(name, title, color) +{ + this.name = name; + this.title = title; + this.color = color; +} WebInspector.TimelineCalculator = function() { - WebInspector.AbstractTimelineCalculator.call(this); + this.windowLeft = 0.0; + this.windowRight = 1.0; + this._uiString = WebInspector.UIString.bind(WebInspector); } WebInspector.TimelineCalculator.prototype = { computeBarGraphPercentages: function(record) { - var start = ((record.startTime - this.minimumBoundary) / this.boundarySpan) * 100; - var end = ((record.endTime - this.minimumBoundary) / this.boundarySpan) * 100; + var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100; return {start: start, end: end}; }, - computePercentageFromEventTime: function(eventTime) + get minimumBoundary() + { + if (typeof this._minimumBoundary === "number") + return this._minimumBoundary; + + if (typeof this.windowLeft === "number") + this._minimumBoundary = this._absoluteMinimumBoundary + this.windowLeft * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + else + this._minimumBoundary = this._absoluteMinimumBoundary; + return this._minimumBoundary; + }, + + get maximumBoundary() { - return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100; + if (typeof this._maximumBoundary === "number") + return this._maximumBoundary; + + if (typeof this.windowLeft === "number") + this._maximumBoundary = this._absoluteMinimumBoundary + this.windowRight * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + else + this._maximumBoundary = this._absoluteMaximumBoundary; + return this._maximumBoundary; }, - computeBarGraphLabels: function(record) + reset: function() { - return {tooltip: record.title}; + delete this._absoluteMinimumBoundary; + delete this._absoluteMaximumBoundary; + delete this._minimumBoundary; + delete this._maximumBoundary; }, updateBoundaries: function(record) @@ -287,76 +478,153 @@ WebInspector.TimelineCalculator.prototype = { var lowerBound = record.startTime; - if (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary) { - this.minimumBoundary = lowerBound; + if (typeof this._absoluteMinimumBoundary === "undefined" || lowerBound < this._absoluteMinimumBoundary) { + this._absoluteMinimumBoundary = lowerBound; + delete this._minimumBoundary; didChange = true; } var upperBound = record.endTime; - if (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary) { - this.maximumBoundary = upperBound; + if (typeof this._absoluteMaximumBoundary === "undefined" || upperBound > this._absoluteMaximumBoundary) { + this._absoluteMaximumBoundary = upperBound; + delete this._maximumBoundary; didChange = true; } return didChange; }, - formatValue: function(value) + get boundarySpan() { - return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector)); + return this.maximumBoundary - this.minimumBoundary; }, + formatValue: function(value) + { + return Number.secondsToString(value + this.minimumBoundary - this._absoluteMinimumBoundary, this._uiString); + } } -WebInspector.TimelineCalculator.prototype.__proto__ = WebInspector.AbstractTimelineCalculator.prototype; - -WebInspector.TimelineGraph = function(record) +WebInspector.TimelineRecordListRow = function() { - this.record = record; + this.element = document.createElement("div"); + this.element.listRow = this; + var iconElement = document.createElement("span"); + iconElement.className = "timeline-tree-icon"; + this.element.appendChild(iconElement); - this._graphElement = document.createElement("div"); - this._graphElement.className = "timeline-graph-side"; + this._typeElement = document.createElement("span"); + this._typeElement.className = "type"; + this.element.appendChild(this._typeElement); - this._barAreaElement = document.createElement("div"); - this._barAreaElement.className = "timeline-graph-bar-area hidden"; - this._graphElement.appendChild(this._barAreaElement); + var separatorElement = document.createElement("span"); + separatorElement.className = "separator"; + separatorElement.textContent = " "; - this._barElement = document.createElement("div"); - this._barElement.className = "timeline-graph-bar"; - this._barAreaElement.appendChild(this._barElement); + this._dataElement = document.createElement("span"); + this._dataElement.className = "data dimmed"; + + this._repeatCountElement = document.createElement("span"); + this._repeatCountElement.className = "count"; - this._graphElement.addStyleClass("timeline-category-" + record.category.name); + this.element.appendChild(separatorElement); + this.element.appendChild(this._dataElement); + this.element.appendChild(this._repeatCountElement); } -WebInspector.TimelineGraph.prototype = { - get graphElement() +WebInspector.TimelineRecordListRow.prototype = { + update: function(record, isEven) { - return this._graphElement; - }, + this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : ""); + this._typeElement.textContent = record.title; - refreshLabelPositions: function() - { + if (record.details) { + this._dataElement.textContent = "(" + record.details + ")"; + this._dataElement.title = record.details; + } else { + this._dataElement.textContent = ""; + this._dataElement.title = ""; + } + + if (record.count > 1) + this._repeatCountElement.textContent = "\u2009\u00d7\u2009" + record.count; + else + this._repeatCountElement.textContent = ""; }, - refresh: function(calculator) + dispose: function() { - var percentages = calculator.computeBarGraphPercentages(this.record); - var labels = calculator.computeBarGraphLabels(this.record); + this.element.parentElement.removeChild(this.element); + } +} - this._percentages = percentages; - this._barAreaElement.removeStyleClass("hidden"); +WebInspector.TimelineRecordGraphRow = function(graphContainer, refreshCallback, rowHeight) +{ + this.element = document.createElement("div"); + this.element.graphRow = this; - if (!this._graphElement.hasStyleClass("timeline-category-" + this.record.category.name)) { - this._graphElement.removeMatchingStyleClasses("timeline-category-\\w+"); - this._graphElement.addStyleClass("timeline-category-" + this.record.category.name); + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "timeline-graph-bar-area"; + this.element.appendChild(this._barAreaElement); + + this._barElement = document.createElement("div"); + this._barElement.className = "timeline-graph-bar"; + this._barAreaElement.appendChild(this._barElement); + + this._expandElement = document.createElement("div"); + this._expandElement.className = "timeline-expandable"; + graphContainer.appendChild(this._expandElement); + + var leftBorder = document.createElement("div"); + leftBorder.className = "timeline-expandable-left"; + this._expandElement.appendChild(leftBorder); + + this._expandElement.addEventListener("click", this._onClick.bind(this)); + this._refreshCallback = refreshCallback; + this._rowHeight = rowHeight; +} + +WebInspector.TimelineRecordGraphRow.prototype = { + update: function(record, isEven, calculator, clientWidth, expandOffset) + { + this._record = record; + this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : ""); + var percentages = calculator.computeBarGraphPercentages(record); + var left = percentages.start / 100 * clientWidth; + var width = (percentages.end - percentages.start) / 100 * clientWidth; + this._barElement.style.left = (left + expandOffset) + "px"; + this._barElement.style.width = width + "px"; + + if (record.visibleChildrenCount) { + this._expandElement.style.top = this.element.offsetTop + "px"; + this._expandElement.style.left = left + "px"; + this._expandElement.style.width = Math.max(12, width + 25) + "px"; + if (!record.collapsed) { + this._expandElement.style.height = (record.visibleChildrenCount + 1) * this._rowHeight + "px"; + this._expandElement.addStyleClass("timeline-expandable-expanded"); + this._expandElement.removeStyleClass("timeline-expandable-collapsed"); + } else { + this._expandElement.style.height = this._rowHeight + "px"; + this._expandElement.addStyleClass("timeline-expandable-collapsed"); + this._expandElement.removeStyleClass("timeline-expandable-expanded"); + } + this._expandElement.removeStyleClass("hidden"); + } else { + this._expandElement.addStyleClass("hidden"); } + }, - this._barElement.style.setProperty("left", percentages.start + "%"); - this._barElement.style.setProperty("right", (100 - percentages.end) + "%"); + _onClick: function(event) + { + this._record.collapsed = !this._record.collapsed; + this._refreshCallback(); + }, - var tooltip = (labels.tooltip || ""); - this._barElement.title = tooltip; + dispose: function() + { + this.element.parentElement.removeChild(this.element); + this._expandElement.parentElement.removeChild(this._expandElement); } } |
