diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js index 6770170ba098b..01ba42848ac4a 100644 Binary files a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js and b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js differ diff --git a/Source/WebInspectorUI/UserInterface/DataGrid.js b/Source/WebInspectorUI/UserInterface/DataGrid.js index d09808ab08516..e423cc08546a3 100644 --- a/Source/WebInspectorUI/UserInterface/DataGrid.js +++ b/Source/WebInspectorUI/UserInterface/DataGrid.js @@ -1303,7 +1303,7 @@ WebInspector.DataGridNode = function(data, hasChildren) this._data = data || {}; this.hasChildren = hasChildren || false; this.children = []; - this.dataGrid = this.dataGrid || null; + this.dataGrid = null; this.parent = null; this.previousSibling = null; this.nextSibling = null; diff --git a/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen.png b/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen.png new file mode 100644 index 0000000000000..06a89e28ceb70 Binary files /dev/null and b/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen.png differ diff --git a/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen@2x.png b/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen@2x.png new file mode 100644 index 0000000000000..d5b36ec1cda42 Binary files /dev/null and b/Source/WebInspectorUI/UserInterface/Images/TimelineBarGreen@2x.png differ diff --git a/Source/WebInspectorUI/UserInterface/InstrumentIcons.css b/Source/WebInspectorUI/UserInterface/InstrumentIcons.css index 6ccde5b2ccb96..7e17595d6c5cb 100644 --- a/Source/WebInspectorUI/UserInterface/InstrumentIcons.css +++ b/Source/WebInspectorUI/UserInterface/InstrumentIcons.css @@ -31,6 +31,10 @@ content: -webkit-image-set(url(Images/Colors.png) 1x, url(Images/Colors@2x.png) 2x); } +.screenshot-icon .icon { + content: -webkit-image-set(url(Images/Log.png) 1x, url(Images/Log@2x.png) 2x); +} + .script-icon .icon { content: -webkit-image-set(url(Images/Script.png) 1x, url(Images/Script@2x.png) 2x); } diff --git a/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.css b/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.css index a6b7b2373cf90..e110b3d2dd366 100644 --- a/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.css +++ b/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.css @@ -56,7 +56,7 @@ outline: none; color: transparent; overflow: hidden; - + -webkit-appearance: none; background-color: transparent; @@ -98,7 +98,7 @@ top: 22px; left: 0; right: 0; - height: 78px; + height: 104px; } .sidebar > .panel.instrument > .navigation-sidebar-panel-content-tree-outline.timelines .item:not(:first-child):not(.selected) { @@ -110,7 +110,7 @@ } .sidebar > .panel.instrument > .title-bar.profiles { - top: 100px; + top: 126px; border-top: 1px solid rgb(179, 179, 179); height: 23px; } diff --git a/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.js b/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.js index b57c4f6a997fe..46c5f19f23a14 100644 --- a/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.js +++ b/Source/WebInspectorUI/UserInterface/InstrumentSidebarPanel.js @@ -75,10 +75,16 @@ WebInspector.InstrumentSidebarPanel = function() scriptTimelineTreeElement.twoLine = true; this._timelinesTreeOutline.appendChild(scriptTimelineTreeElement); + var screenshotTimelineTreeElement = new WebInspector.GeneralTreeElement(WebInspector.InstrumentSidebarPanel.ScreenshotIconStyleClass, WebInspector.UIString("Screenshots"), null, WebInspector.TimelineRecord.Type.Screenshot); + screenshotTimelineTreeElement.small = true; + screenshotTimelineTreeElement.twoLine = true; + this._timelinesTreeOutline.appendChild(screenshotTimelineTreeElement); + this._timelineTreeElementMap = {}; this._timelineTreeElementMap[WebInspector.TimelineRecord.Type.Network] = networkTimelineTreeElement; this._timelineTreeElementMap[WebInspector.TimelineRecord.Type.Layout] = layoutTimelineTreeElement; this._timelineTreeElementMap[WebInspector.TimelineRecord.Type.Script] = scriptTimelineTreeElement; + this._timelineTreeElementMap[WebInspector.TimelineRecord.Type.Screenshot] = screenshotTimelineTreeElement; var profilesTitleBarElement = document.createElement("div"); profilesTitleBarElement.textContent = WebInspector.UIString("Profiles"); @@ -132,6 +138,8 @@ WebInspector.InstrumentSidebarPanel = function() WebInspector.profileManager.addEventListener(WebInspector.ProfileManager.Event.ProfilingEnded, this._profilingEnded, this); WebInspector.profileManager.addEventListener(WebInspector.ProfileManager.Event.ProfilingInterrupted, this._profilingInterrupted, this); + this._isCapturingScreenshots = true; + this.emptyContentPlaceholder = WebInspector.UIString("No Recorded Profiles"); // Maps from profile titles -> tree elements. @@ -154,6 +162,7 @@ WebInspector.InstrumentSidebarPanel.NetworkIconStyleClass = "network-icon"; WebInspector.InstrumentSidebarPanel.ColorsIconStyleClass = "colors-icon"; WebInspector.InstrumentSidebarPanel.ScriptIconStyleClass = "script-icon"; WebInspector.InstrumentSidebarPanel.ProfileIconStyleClass = "profile-icon"; +WebInspector.InstrumentSidebarPanel.ScreenshotIconStyleClass = "screenshot-icon"; WebInspector.InstrumentSidebarPanel.StartJavaScriptProfileValue = "start-javascript-profile"; WebInspector.InstrumentSidebarPanel.StartCSSSelectorProfileValue = "start-css-selector-profile"; WebInspector.InstrumentSidebarPanel.StartCanvasProfileValue = "start-canvas-profile"; @@ -411,10 +420,15 @@ WebInspector.InstrumentSidebarPanel.prototype = { // Add forced class to prevent the glyph from showing a confusing status after click. this._recordGlyphElement.classList.add(WebInspector.InstrumentSidebarPanel.RecordGlyphRecordingForcedStyleClass); - if (WebInspector.timelineManager.recording) + if (WebInspector.timelineManager.recording) { WebInspector.timelineManager.stopRecording(); - else + if (this._isCapturingScreenshots) + WebInspector.timelineManager.clearScreenshotInterval(); + } else { WebInspector.timelineManager.startRecording(); + if (this._isCapturingScreenshots) + WebInspector.timelineManager.setScreenshotInterval(); + } }, _titleForProfile: function(profile) diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html index 5f6ee410e07f7..11bfcefe46a8e 100644 --- a/Source/WebInspectorUI/UserInterface/Main.html +++ b/Source/WebInspectorUI/UserInterface/Main.html @@ -351,6 +351,7 @@ + @@ -358,6 +359,8 @@ + + diff --git a/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGrid.js b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGrid.js new file mode 100644 index 0000000000000..9b2226a19939e --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGrid.js @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + WebInspector.ScreenshotTimelineDataGrid = function(columns) +{ + WebInspector.TimelineDataGrid.call(this, columns); + + this.element.classList.add(WebInspector.ScreenshotTimelineDataGrid.ScreenshotDataGridStyleClassName); +} + +WebInspector.ScreenshotTimelineDataGrid.ScreenshotDataGridStyleClassName = "screenshot-data-grid"; + +WebInspector.ScreenshotTimelineDataGrid.prototype = { + constructor: WebInspector.ScreenshotTimelineDataGrid, + __proto__: WebInspector.TimelineDataGrid.prototype, + + // Protected + + callFramePopoverAnchorElement: function() + { + return this.selectedNode.elementWithColumnIdentifier("image"); + } +} diff --git a/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGridNode.js new file mode 100644 index 0000000000000..4af5f128492b5 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineDataGridNode.js @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + WebInspector.ScreenshotTimelineDataGridNode = function(screenshotTimelineRecord, baseStartTime) +{ + WebInspector.DataGridNode.call(this, {}); + + this._record = screenshotTimelineRecord; + this._baseStartTime = baseStartTime || 0; +}; + +WebInspector.Object.addConstructorFunctions(WebInspector.ScreenshotTimelineDataGridNode); + +WebInspector.ScreenshotTimelineDataGridNode.IconStyleClassName = "icon"; +WebInspector.ScreenshotTimelineDataGridNode.SubtitleStyleClassName = "subtitle"; +WebInspector.ScreenshotTimelineDataGridNode.EmptyImagePlaceholder = "Images/DocumentImage.png"; +WebInspector.ScreenshotTimelineDataGridNode.EmptyStringPlaceholder = "\u2014"; +WebInspector.ScreenshotTimelineDataGridNode.ScreenshotStyleClassName = "screenshot"; +WebInspector.ScreenshotTimelineDataGridNode.EmptyScreenshotStyleClassName = "empty"; + +WebInspector.ScreenshotTimelineDataGridNode.prototype = { + constructor: WebInspector.ScreenshotTimelineDataGridNode, + __proto__: WebInspector.DataGridNode.prototype, + + // Public + + get record() + { + return this._record; + }, + + get data() + { + return this._record; + }, + + createCellContent: function(columnIdentifier, cell) + { + var emptyString = WebInspector.ScreenshotTimelineDataGridNode.EmptyStringPlaceholder; + var value = this.data[columnIdentifier]; + + switch (columnIdentifier) { + case "eventType": + return WebInspector.ScreenshotTimelineRecord.EventType.displayName(value); + + case "image": + var source = value; + var image = document.createElement("img"); + image.classList.add(WebInspector.ScreenshotTimelineDataGridNode.ScreenshotStyleClassName); + + if (!source) { + image.src = WebInspector.ScreenshotTimelineDataGridNode.EmptyImagePlaceholder; + image.classList.add(WebInspector.ScreenshotTimelineDataGridNode.EmptyScreenshotStyleClassName); + } else { + image.src = source; + } + + return image; + + case "x": + case "y": + return isNaN(value) ? emptyString : WebInspector.UIString("%d").format(value); + + case "width": + case "height": + return isNaN(value) ? emptyString : WebInspector.UIString("%fpx").format(value); + + case "area": + return isNaN(value) ? emptyString : WebInspector.UIString("%fpx²").format(value); + + case "startTime": + return isNaN(value) ? emptyString : Number.secondsToString(value - this._baseStartTime); + } + + return WebInspector.DataGridNode.prototype.createCellContent.call(this, columnIdentifier); + } +} diff --git a/Source/WebInspectorUI/UserInterface/ScreenshotTimelineRecord.js b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineRecord.js new file mode 100644 index 0000000000000..c254d9300d2ce --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/ScreenshotTimelineRecord.js @@ -0,0 +1,94 @@ + +/* + * Copyright (C) 2013 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + WebInspector.ScreenshotTimelineRecord = function(startTime, image, x, y, width, height) +{ + WebInspector.TimelineRecord.call(this, WebInspector.TimelineRecord.Type.Screenshot, startTime, startTime); + + this._startTime = startTime || NaN; + this._x = x || NaN; + this._y = y || NaN; + this._width = width || NaN; + this._height = height || NaN; + this._image = image; +}; + +WebInspector.ScreenshotTimelineRecord.EventType = { + ImageCaptured: "screenshot-image-captured" +}; + +WebInspector.ScreenshotTimelineRecord.EventType.displayName = function(eventType) +{ + return WebInspector.UIString("Image Captured"); +}; + +WebInspector.ScreenshotTimelineRecord.prototype = { + constructor: WebInspector.ScreenshotTimelineRecord, + + // Public + + get eventType() + { + return WebInspector.ScreenshotTimelineRecord.EventType.ImageCaptured; + }, + + get startTime() + { + return this._startTime; + }, + + get x() + { + return this._x; + }, + + get y() + { + return this._y; + }, + + get width() + { + return this._width; + }, + + get height() + { + return this._height; + }, + + get area() + { + return this._width * this._height; + }, + + get image() + { + return this._image; + } +}; + +WebInspector.ScreenshotTimelineRecord.prototype.__proto__ = WebInspector.TimelineRecord.prototype; diff --git a/Source/WebInspectorUI/UserInterface/TimelineDecorations.css b/Source/WebInspectorUI/UserInterface/TimelineDecorations.css index 01c465c0528fc..55898d3c15e3d 100644 --- a/Source/WebInspectorUI/UserInterface/TimelineDecorations.css +++ b/Source/WebInspectorUI/UserInterface/TimelineDecorations.css @@ -31,7 +31,7 @@ .timeline-decorations > .header { border-top: 1px solid rgb(200, 200, 200); - height: 22px; + height: 23px; position: relative; } diff --git a/Source/WebInspectorUI/UserInterface/TimelineManager.js b/Source/WebInspectorUI/UserInterface/TimelineManager.js index c5fb8d6fb6aff..5ddaad701cd9e 100644 --- a/Source/WebInspectorUI/UserInterface/TimelineManager.js +++ b/Source/WebInspectorUI/UserInterface/TimelineManager.js @@ -50,6 +50,7 @@ WebInspector.TimelineManager.Event = { WebInspector.TimelineManager.MaximumAutoRecordDuration = 90000; // 90 seconds WebInspector.TimelineManager.MaximumAutoRecordDurationAfterLoadEvent = 10000; // 10 seconds WebInspector.TimelineManager.DeadTimeRequiredToStopAutoRecordingEarly = 2000; // 2 seconds +WebInspector.TimelineManager.ScreenshotTimeIntervalDelay = 1000; // 1 second WebInspector.TimelineManager.prototype = { constructor: WebInspector.TimelineManager, @@ -299,6 +300,14 @@ WebInspector.TimelineManager.prototype = { this._loadEventTime = timestamp; }, + setScreenshotInterval: function() { + this._timeInvervalIdentifier = setInterval(this._recordScreenshot.bind(this), WebInspector.TimelineManager.ScreenshotTimeIntervalDelay); + }, + + clearScreenshotInterval: function() { + clearInterval(this._timeInvervalIdentifier); + }, + // Private _clear: function() @@ -434,6 +443,14 @@ WebInspector.TimelineManager.prototype = { return; this._addRecord(new WebInspector.ResourceTimelineRecord(event.data.resource)); + }, + + _recordScreenshot: function() + { + PageAgent.snapshotRect(0, 0, document.width, document.height, "Viewport", function(error, dataURL) { + if (!error) + this._addRecord(new WebInspector.ScreenshotTimelineRecord((new Date().getTime()) / 1000, dataURL, 0, 0, document.width, document.height)); + }.bind(this)); } }; diff --git a/Source/WebInspectorUI/UserInterface/TimelineOverview.css b/Source/WebInspectorUI/UserInterface/TimelineOverview.css index be237e3cdf960..fe30719858b45 100644 --- a/Source/WebInspectorUI/UserInterface/TimelineOverview.css +++ b/Source/WebInspectorUI/UserInterface/TimelineOverview.css @@ -66,6 +66,10 @@ border-image-source: -webkit-image-set(url(Images/TimelineBarOrange.png) 1x, url(Images/TimelineBarOrange@2x.png) 2x); } +.timeline-overview > .timeline.timeline-record-type-screenshot .bar { + border-image-source: -webkit-image-set(url(Images/TimelineBarGreen.png) 1x, url(Images/TimelineBarGreen@2x.png) 2x); +} + .timeline-overview .timeline-decorations > .event-markers { height: 78px; bottom: 22px; diff --git a/Source/WebInspectorUI/UserInterface/TimelineRecord.js b/Source/WebInspectorUI/UserInterface/TimelineRecord.js index 06388eee40fc4..f89b9bc9b6f0a 100644 --- a/Source/WebInspectorUI/UserInterface/TimelineRecord.js +++ b/Source/WebInspectorUI/UserInterface/TimelineRecord.js @@ -44,6 +44,7 @@ WebInspector.TimelineRecord.Event = { WebInspector.TimelineRecord.Type = { Network: "timeline-record-type-network", Layout: "timeline-record-type-layout", + Screenshot: "timeline-record-type-screenshot", Script: "timeline-record-type-script" }; diff --git a/Source/WebInspectorUI/UserInterface/TimelinesContentView.css b/Source/WebInspectorUI/UserInterface/TimelinesContentView.css index 93720719d134d..5d0e2a3cb6f54 100644 --- a/Source/WebInspectorUI/UserInterface/TimelinesContentView.css +++ b/Source/WebInspectorUI/UserInterface/TimelinesContentView.css @@ -28,12 +28,12 @@ top: 0; left: 0; right: 0; - height: 100px; + height: 125px; } .content-view.timelines > .data-grid { position: absolute; - top: 100px; + top: 126px; left: 0; right: 0; bottom: 0; @@ -245,3 +245,21 @@ border-bottom: 1px solid rgb(179, 179, 179); background-color: white; } + +.content-view.timelines > .data-grid img.screenshot { + height: 300px; +} + +.content-view.timelines > .data-grid.screenshot-data-grid tr.offscreen { + height: 300px; +} + +.content-view.timelines > .data-grid.screenshot-data-grid tr.offscreen td { + display: block; +} + +.content-view.timelines > .data-grid.screenshot-data-grid table.data { + background-size: auto 600px; + background-image: -webkit-linear-gradient(top, #ccc, #ccc 50%, rgb(90%, 90%, 90%) 50%, rgb(90%, 90%, 90%)); + +} diff --git a/Source/WebInspectorUI/UserInterface/TimelinesContentView.js b/Source/WebInspectorUI/UserInterface/TimelinesContentView.js index 6a9b31af2548c..4a3cfc57c4048 100644 --- a/Source/WebInspectorUI/UserInterface/TimelinesContentView.js +++ b/Source/WebInspectorUI/UserInterface/TimelinesContentView.js @@ -29,7 +29,7 @@ WebInspector.TimelinesContentView = function(representedObject) this.element.classList.add(WebInspector.TimelinesContentView.StyleClassName); - this._timelineOverview = new WebInspector.TimelineOverview(this, [WebInspector.TimelineRecord.Type.Network, WebInspector.TimelineRecord.Type.Layout, WebInspector.TimelineRecord.Type.Script]); + this._timelineOverview = new WebInspector.TimelineOverview(this, [WebInspector.TimelineRecord.Type.Network, WebInspector.TimelineRecord.Type.Layout, WebInspector.TimelineRecord.Type.Script, WebInspector.TimelineRecord.Type.Screenshot]); this.element.appendChild(this._timelineOverview.element); function createPathComponent(displayName, className, representedObject) @@ -42,11 +42,15 @@ WebInspector.TimelinesContentView = function(representedObject) var networkPathComponent = createPathComponent.call(this, WebInspector.UIString("Network Requests"), WebInspector.InstrumentSidebarPanel.NetworkIconStyleClass, WebInspector.TimelineRecord.Type.Network); var layoutPathComponent = createPathComponent.call(this, WebInspector.UIString("Layout & Rendering"), WebInspector.InstrumentSidebarPanel.ColorsIconStyleClass, WebInspector.TimelineRecord.Type.Layout); var scriptPathComponent = createPathComponent.call(this, WebInspector.UIString("JavaScript & Events"), WebInspector.InstrumentSidebarPanel.ScriptIconStyleClass, WebInspector.TimelineRecord.Type.Script); + var screenshotPathComponent = createPathComponent.call(this, WebInspector.UIString("Screenshots"), WebInspector.InstrumentSidebarPanel.ScreenshotIconStyleClass, WebInspector.TimelineRecord.Type.Screenshot); networkPathComponent.nextSibling = layoutPathComponent; layoutPathComponent.previousSibling = networkPathComponent; layoutPathComponent.nextSibling = scriptPathComponent; scriptPathComponent.previousSibling = layoutPathComponent; + scriptPathComponent.nextSibling = screenshotPathComponent; + screenshotPathComponent.previousSibling = scriptPathComponent; + this._currentRecordType = null; this._currentRecordTypeSetting = new WebInspector.Setting("timeline-view-current-record-type", WebInspector.TimelineRecord.Type.Network); @@ -147,6 +151,35 @@ WebInspector.TimelinesContentView = function(representedObject) scriptDataGridColumns.duration.width = "10%"; scriptDataGridColumns.duration.aligned = "right"; + var screenshotDataGridColumns = {eventType: {}, image: {}, x: {}, y: {}, width: {}, height: {}, area: {}, startTime: {}}; + + screenshotDataGridColumns.eventType.title = WebInspector.UIString("Type"); + screenshotDataGridColumns.eventType.width = "15%"; + screenshotDataGridColumns.eventType.scopeBar = this._makeColumnScopeBar("screenshot", WebInspector.ScreenshotTimelineRecord.EventType); + + screenshotDataGridColumns.image.title = WebInspector.UIString("Image"); + screenshotDataGridColumns.image.width = "25%"; + + screenshotDataGridColumns.x.title = WebInspector.UIString("X"); + screenshotDataGridColumns.x.width = "8%"; + + screenshotDataGridColumns.y.title = WebInspector.UIString("Y"); + screenshotDataGridColumns.y.width = "8%"; + + screenshotDataGridColumns.width.title = WebInspector.UIString("Width"); + screenshotDataGridColumns.width.width = "8%"; + + screenshotDataGridColumns.height.title = WebInspector.UIString("Height"); + screenshotDataGridColumns.width.width = "8%"; + + screenshotDataGridColumns.area.title = WebInspector.UIString("Area"); + screenshotDataGridColumns.area.width = "12%"; + + screenshotDataGridColumns.startTime.title = WebInspector.UIString("Time"); + screenshotDataGridColumns.startTime.width = "8%"; + screenshotDataGridColumns.startTime.aligned = "right"; + screenshotDataGridColumns.startTime.sort = "ascending"; + for (var column in networkDataGridColumns) networkDataGridColumns[column].sortable = true; @@ -156,9 +189,13 @@ WebInspector.TimelinesContentView = function(representedObject) for (var column in scriptDataGridColumns) scriptDataGridColumns[column].sortable = true; + for (var column in screenshotDataGridColumns) + screenshotDataGridColumns[column].sortable = true; + var networkDataGrid = new WebInspector.NetworkDataGrid(networkDataGridColumns); var layoutDataGrid = new WebInspector.LayoutTimelineDataGrid(layoutDataGridColumns); var scriptDataGrid = new WebInspector.ScriptTimelineDataGrid(scriptDataGridColumns); + var screenshotDataGrid = new WebInspector.ScreenshotTimelineDataGrid(screenshotDataGridColumns); networkDataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._selectedNodeChanged, this); @@ -166,11 +203,13 @@ WebInspector.TimelinesContentView = function(representedObject) this._pathComponentMap[WebInspector.TimelineRecord.Type.Network] = networkPathComponent; this._pathComponentMap[WebInspector.TimelineRecord.Type.Layout] = layoutPathComponent; this._pathComponentMap[WebInspector.TimelineRecord.Type.Script] = scriptPathComponent; + this._pathComponentMap[WebInspector.TimelineRecord.Type.Screenshot] = screenshotPathComponent; this._dataGridMap = {}; this._dataGridMap[WebInspector.TimelineRecord.Type.Network] = networkDataGrid; this._dataGridMap[WebInspector.TimelineRecord.Type.Layout] = layoutDataGrid; this._dataGridMap[WebInspector.TimelineRecord.Type.Script] = scriptDataGrid; + this._dataGridMap[WebInspector.TimelineRecord.Type.Screenshot] = screenshotDataGrid; for (var type in this._dataGridMap) { var dataGrid = this._dataGridMap[type]; @@ -658,6 +697,8 @@ WebInspector.TimelinesContentView.prototype = { return new WebInspector.LayoutTimelineDataGridNode(record, baseStartTime); case WebInspector.TimelineRecord.Type.Script: return new WebInspector.ScriptTimelineDataGridNode(record, baseStartTime); + case WebInspector.TimelineRecord.Type.Screenshot: + return new WebInspector.ScreenshotTimelineDataGridNode(record, baseStartTime); } console.error("Unknown record type: " + record.type);