Web Inspector: discontinuous recordings should have discontinuities in the timeline...
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / HeapAllocationsTimelineOverviewGraph.js
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.HeapAllocationsTimelineOverviewGraph = class HeapAllocationsTimelineOverviewGraph extends WebInspector.TimelineOverviewGraph
27 {
28     constructor(timeline, timelineOverview)
29     {
30         super(timelineOverview);
31
32         this.element.classList.add("heap-allocations");
33
34         this._heapAllocationsTimeline = timeline;
35         this._heapAllocationsTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._heapAllocationTimelineRecordAdded, this);
36
37         this._selectedImageElement = null;
38
39         this.reset();
40     }
41
42     // Protected
43
44     reset()
45     {
46         super.reset();
47
48         this.element.removeChildren();
49     }
50
51     layout()
52     {
53         if (!this.visible)
54             return;
55
56         this.element.removeChildren();
57         this._selectedImageElement = null;
58
59         // This may display records past the current time marker.
60         let visibleRecords = this._heapAllocations.recordsInTimeRange(this.startTime, this.endTime);
61         if (!visibleRecords.length)
62             return;
63
64         let graphStartTime = this.startTime;
65         let secondsPerPixel = this.timelineOverview.secondsPerPixel;
66
67         function xScale(time) {
68             return (time - graphStartTime) / secondsPerPixel;
69         }
70
71         for (let record of visibleRecords) {
72             const halfImageWidth = 8;
73             let x = xScale(record.timestamp) - halfImageWidth;
74             if (x <= 1)
75                 x = 1;
76
77             let imageElement = record[WebInspector.HeapAllocationsTimelineOverviewGraph.RecordElementAssociationSymbol];
78             if (!imageElement) {
79                 imageElement = document.createElement("img");
80                 imageElement.classList.add("snapshot");
81                 imageElement.addEventListener("click", () => { this.selectedRecord = record; });
82                 record[WebInspector.HeapAllocationsTimelineOverviewGraph.RecordElementAssociationSymbol] = imageElement;
83             }
84
85             imageElement.style.left = x + "px";
86
87             this.element.appendChild(imageElement);
88         }
89
90         this._updateSnapshotMarkers();
91     }
92
93     updateSelectedRecord()
94     {
95         this._updateSnapshotMarkers();
96     }
97
98     // Private
99
100     _updateSnapshotMarkers()
101     {
102         if (this._selectedImageElement)
103             this._selectedImageElement.classList.remove("selected");
104
105         if (!this.selectedRecord) {
106             this._selectedImageElement = null;
107             return;
108         }
109
110         let imageElement = this.selectedRecord[WebInspector.HeapAllocationsTimelineOverviewGraph.RecordElementAssociationSymbol];
111         console.assert(imageElement, "Missing snapshot image element for selected record", this.selectedRecord);
112         imageElement.classList.add("selected");
113
114         this._selectedImageElement = imageElement;
115     }
116
117     _heapAllocationTimelineRecordAdded(event)
118     {
119         this.needsLayout();
120     }
121 };
122
123 WebInspector.HeapAllocationsTimelineOverviewGraph.RecordElementAssociationSymbol = Symbol("record-element-association");