Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/resources/tracing/timeline_track.js

Issue 10161025: Allow about:tracing Counters to be selected (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 /** 6 /**
7 * @fileoverview Renders an array of slices into the provided div, 7 * @fileoverview Renders an array of slices into the provided div,
8 * using a child canvas element. Uses a FastRectRenderer to draw only 8 * using a child canvas element. Uses a FastRectRenderer to draw only
9 * the visible slices. 9 * the visible slices.
10 */ 10 */
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 this.updateChildTracks_(); 63 this.updateChildTracks_();
64 }, 64 },
65 65
66 get firstCanvas() { 66 get firstCanvas() {
67 if (this.tracks_.length) 67 if (this.tracks_.length)
68 return this.tracks_[0].firstCanvas; 68 return this.tracks_[0].firstCanvas;
69 return undefined; 69 return undefined;
70 }, 70 },
71 71
72 /** 72 /**
73 * Picks a slice, if any, at a given location. 73 * Adds items intersecting a point to a selection.
74 * @param {number} wX X location to search at, in worldspace. 74 * @param {number} wX X location to search at, in worldspace.
75 * @param {number} wY Y location to search at, in offset space. 75 * @param {number} wY Y location to search at, in offset space.
76 * offset space. 76 * offset space.
77 * @param {function():*} onHitCallback Callback to call with the slice, 77 * @param {TimelineSelection} selection Selection to which to add hits.
78 * if one is found.
79 * @return {boolean} true if a slice was found, otherwise false. 78 * @return {boolean} true if a slice was found, otherwise false.
80 */ 79 */
81 pick: function(wX, wY, onHitCallback) { 80 addIntersectingItemsToSelection: function(wX, wY, selection) {
82 for (var i = 0; i < this.tracks_.length; i++) { 81 for (var i = 0; i < this.tracks_.length; i++) {
83 var trackClientRect = this.tracks_[i].getBoundingClientRect(); 82 var trackClientRect = this.tracks_[i].getBoundingClientRect();
84 if (wY >= trackClientRect.top && wY < trackClientRect.bottom) 83 if (wY >= trackClientRect.top && wY < trackClientRect.bottom)
85 return this.tracks_[i].pick(wX, onHitCallback); 84 this.tracks_[i].addIntersectingItemsToSelection(wX, wY, selection);
86 } 85 }
87 return false; 86 return false;
88 }, 87 },
89 88
90 /** 89 /**
91 * Finds slices intersecting the given interval. 90 * Adds items intersecting the given range to a selection.
92 * @param {number} loWX Lower X bound of the interval to search, in 91 * @param {number} loWX Lower X bound of the interval to search, in
93 * worldspace. 92 * worldspace.
94 * @param {number} hiWX Upper X bound of the interval to search, in 93 * @param {number} hiWX Upper X bound of the interval to search, in
95 * worldspace. 94 * worldspace.
96 * @param {number} loY Lower Y bound of the interval to search, in 95 * @param {number} loY Lower Y bound of the interval to search, in
97 * offset space. 96 * offset space.
98 * @param {number} hiY Upper Y bound of the interval to search, in 97 * @param {number} hiY Upper Y bound of the interval to search, in
99 * offset space. 98 * offset space.
100 * @param {function():*} onHitCallback Function to call for each slice 99 * @param {TimelineSelection} selection Selection to which to add hits.
101 * intersecting the interval.
102 */ 100 */
103 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 101 addIntersectingItemsInRangeToSelection: function(
102 loWX, hiWX, loY, hiY, selection) {
104 for (var i = 0; i < this.tracks_.length; i++) { 103 for (var i = 0; i < this.tracks_.length; i++) {
105 var trackClientRect = this.tracks_[i].getBoundingClientRect(); 104 var trackClientRect = this.tracks_[i].getBoundingClientRect();
106 var a = Math.max(loY, trackClientRect.top); 105 var a = Math.max(loY, trackClientRect.top);
107 var b = Math.min(hiY, trackClientRect.bottom); 106 var b = Math.min(hiY, trackClientRect.bottom);
108 if (a <= b) 107 if (a <= b)
109 this.tracks_[i].pickRange(loWX, hiWX, loY, hiY, onHitCallback); 108 this.tracks_[i].addIntersectingItemsInRangeToSelection(
109 loWX, hiWX, loY, hiY, selection);
110 } 110 }
111 }, 111 },
112 112
113 /** 113 addAllObjectsMatchingFilterToSelection: function(filter, selection) {
114 * @return {Array} Objects matching the given filter. 114 for (var i = 0; i < this.tracks_.length; i++)
115 */ 115 this.tracks_[i].addAllObjectsMatchingFilterToSelection(
116 findAllObjectsMatchingFilter: function(filter) { 116 filter, selection);
117 var hits = [];
118 for (var i = 0; i < this.tracks_.length; i++) {
119 var trackHits = this.tracks_[i].findAllObjectsMatchingFilter(filter);
120 Array.prototype.push.apply(hits, trackHits);
121 }
122 return hits;
123 } 117 }
124 }; 118 };
125 119
126 function addControlButtonElements(el, canCollapse) { 120 function addControlButtonElements(el, canCollapse) {
127 var closeEl = document.createElement('div'); 121 var closeEl = document.createElement('div');
128 closeEl.classList.add('timeline-track-button'); 122 closeEl.classList.add('timeline-track-button');
129 closeEl.classList.add('timeline-track-close-button'); 123 closeEl.classList.add('timeline-track-close-button');
130 closeEl.textContent = String.fromCharCode(215); // &times; 124 closeEl.textContent = String.fromCharCode(215); // &times;
131 closeEl.addEventListener('click', function() { 125 closeEl.addEventListener('click', function() {
132 el.style.display = 'None'; 126 el.style.display = 'None';
(...skipping 19 matching lines...) Expand all
152 146
153 /** 147 /**
154 * Visualizes a TimelineThread using a series of of TimelineSliceTracks. 148 * Visualizes a TimelineThread using a series of of TimelineSliceTracks.
155 * @constructor 149 * @constructor
156 */ 150 */
157 var TimelineThreadTrack = cr.ui.define(TimelineContainerTrack); 151 var TimelineThreadTrack = cr.ui.define(TimelineContainerTrack);
158 TimelineThreadTrack.prototype = { 152 TimelineThreadTrack.prototype = {
159 __proto__: TimelineContainerTrack.prototype, 153 __proto__: TimelineContainerTrack.prototype,
160 154
161 decorate: function() { 155 decorate: function() {
156 TimelineContainerTrack.prototype.decorate.call(this);
162 this.classList.add('timeline-thread-track'); 157 this.classList.add('timeline-thread-track');
163 }, 158 },
164 159
165 get thread() { 160 get thread() {
166 return this.thread_; 161 return this.thread_;
167 }, 162 },
168 163
169 set thread(thread) { 164 set thread(thread) {
170 this.thread_ = thread; 165 this.thread_ = thread;
171 this.updateChildTracks_(); 166 this.updateChildTracks_();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 }, 206 },
212 207
213 updateChildTracks_: function() { 208 updateChildTracks_: function() {
214 this.detach(); 209 this.detach();
215 this.textContent = ''; 210 this.textContent = '';
216 this.tracks_ = []; 211 this.tracks_ = [];
217 if (this.thread_) { 212 if (this.thread_) {
218 if (this.thread_.cpuSlices) { 213 if (this.thread_.cpuSlices) {
219 var track = this.addTrack_(this.thread_.cpuSlices); 214 var track = this.addTrack_(this.thread_.cpuSlices);
220 track.height = '4px'; 215 track.height = '4px';
216 track.decorateHit = function(hit) {
217 hit.thread = this.thread_;
218 }
221 } 219 }
222 220
223 if (this.thread_.asyncSlices.length) { 221 if (this.thread_.asyncSlices.length) {
224 var subRows = this.thread_.asyncSlices.subRows; 222 var subRows = this.thread_.asyncSlices.subRows;
225 for (var srI = 0; srI < subRows.length; srI++) { 223 for (var srI = 0; srI < subRows.length; srI++) {
226 var track = this.addTrack_(subRows[srI]); 224 var track = this.addTrack_(subRows[srI]);
225 track.decorateHit = function(hit) {
226 // TODO(simonjam): figure out how to associate subSlice hits back
227 // to their parent slice.
228 }
227 track.asyncStyle = true; 229 track.asyncStyle = true;
228 } 230 }
229 } 231 }
230 232
231 for (var srI = 0; srI < this.thread_.subRows.length; srI++) { 233 for (var srI = 0; srI < this.thread_.subRows.length; srI++) {
232 this.addTrack_(this.thread_.subRows[srI]); 234 var track = this.addTrack_(this.thread_.subRows[srI]);
235 track.decorateHit = function(hit) {
236 hit.thread = this.thread_;
237 }
233 } 238 }
234 239
235 if (this.tracks_.length > 0) { 240 if (this.tracks_.length > 0) {
236 if (this.thread_.cpuSlices) { 241 if (this.thread_.cpuSlices) {
237 this.tracks_[1].heading = this.heading_; 242 this.tracks_[1].heading = this.heading_;
238 this.tracks_[1].tooltip = this.tooltip_; 243 this.tracks_[1].tooltip = this.tooltip_;
239 } else { 244 } else {
240 this.tracks_[0].heading = this.heading_; 245 this.tracks_[0].heading = this.heading_;
241 this.tracks_[0].tooltip = this.tooltip_; 246 this.tracks_[0].tooltip = this.tooltip_;
242 } 247 }
(...skipping 24 matching lines...) Expand all
267 272
268 /** 273 /**
269 * Visualizes a TimelineCpu using a series of of TimelineSliceTracks. 274 * Visualizes a TimelineCpu using a series of of TimelineSliceTracks.
270 * @constructor 275 * @constructor
271 */ 276 */
272 var TimelineCpuTrack = cr.ui.define(TimelineContainerTrack); 277 var TimelineCpuTrack = cr.ui.define(TimelineContainerTrack);
273 TimelineCpuTrack.prototype = { 278 TimelineCpuTrack.prototype = {
274 __proto__: TimelineContainerTrack.prototype, 279 __proto__: TimelineContainerTrack.prototype,
275 280
276 decorate: function() { 281 decorate: function() {
282 TimelineContainerTrack.prototype.decorate.call(this);
277 this.classList.add('timeline-thread-track'); 283 this.classList.add('timeline-thread-track');
278 }, 284 },
279 285
280 get cpu() { 286 get cpu() {
281 return this.cpu_; 287 return this.cpu_;
282 }, 288 },
283 289
284 set cpu(cpu) { 290 set cpu(cpu) {
285 this.cpu_ = cpu; 291 this.cpu_ = cpu;
286 this.updateChildTracks_(); 292 this.updateChildTracks_();
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 /** 514 /**
509 * Should we elide text on trace labels? 515 * Should we elide text on trace labels?
510 * Without eliding, text that is too wide isn't drawn at all. 516 * Without eliding, text that is too wide isn't drawn at all.
511 * Disable if you feel this causes a performance problem. 517 * Disable if you feel this causes a performance problem.
512 * This is a default value that can be overridden in tracks for testing. 518 * This is a default value that can be overridden in tracks for testing.
513 * @const 519 * @const
514 */ 520 */
515 SHOULD_ELIDE_TEXT: true, 521 SHOULD_ELIDE_TEXT: true,
516 522
517 decorate: function() { 523 decorate: function() {
524 CanvasBasedTrack.prototype.decorate.call(this);
518 this.classList.add('timeline-slice-track'); 525 this.classList.add('timeline-slice-track');
519 this.elidedTitleCache = new ElidedTitleCache(); 526 this.elidedTitleCache = new ElidedTitleCache();
520 this.asyncStyle_ = false; 527 this.asyncStyle_ = false;
521 }, 528 },
522 529
530 /**
531 * Called by all the addToSelection functions on the created selection
532 * hit objects. Override this function on parent classes to add
533 * context-specific information to the hit.
534 */
535 decorateHit: function(hit) {
536 },
537
523 get asyncStyle() { 538 get asyncStyle() {
524 return this.asyncStyle_; 539 return this.asyncStyle_;
525 }, 540 },
526 541
527 set asyncStyle(v) { 542 set asyncStyle(v) {
528 this.asyncStyle_ = !!v; 543 this.asyncStyle_ = !!v;
529 this.invalidate(); 544 this.invalidate();
530 }, 545 },
531 546
532 get slices() { 547 get slices() {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 if (drawnWidth * pixWidth < slice.duration) { 676 if (drawnWidth * pixWidth < slice.duration) {
662 var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration); 677 var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration);
663 ctx.fillText(drawnTitle, cX, 2.5, drawnWidth); 678 ctx.fillText(drawnTitle, cX, 2.5, drawnWidth);
664 } 679 }
665 } 680 }
666 } 681 }
667 } 682 }
668 }, 683 },
669 684
670 /** 685 /**
671 * Picks a slice, if any, at a given location. 686 * Finds slices intersecting the given interval.
672 * @param {number} wX X location to search at, in worldspace. 687 * @param {number} wX X location to search at, in worldspace.
673 * @param {number} wY Y location to search at, in offset space. 688 * @param {number} wY Y location to search at, in offset space.
674 * offset space. 689 * offset space.
675 * @param {function():*} onHitCallback Callback to call with the slice, 690 * @param {TimelineSelection} selection Selection to which to add hits.
676 * if one is found.
677 * @return {boolean} true if a slice was found, otherwise false. 691 * @return {boolean} true if a slice was found, otherwise false.
678 */ 692 */
679 pick: function(wX, wY, onHitCallback) { 693 addIntersectingItemsToSelection: function(wX, wY, selection) {
680 var clientRect = this.getBoundingClientRect(); 694 var clientRect = this.getBoundingClientRect();
681 if (wY < clientRect.top || wY >= clientRect.bottom) 695 if (wY < clientRect.top || wY >= clientRect.bottom)
682 return false; 696 return false;
683 var x = tracing.findLowIndexInSortedIntervals(this.slices_, 697 var x = tracing.findLowIndexInSortedIntervals(this.slices_,
684 function(x) { return x.start; }, 698 function(x) { return x.start; },
685 function(x) { return x.duration; }, 699 function(x) { return x.duration; },
686 wX); 700 wX);
687 if (x >= 0 && x < this.slices_.length) { 701 if (x >= 0 && x < this.slices_.length) {
688 onHitCallback('slice', this, this.slices_[x]); 702 var hit = selection.addSlice(this, this.slices_[x]);
703 this.decorateHit(hit);
689 return true; 704 return true;
690 } 705 }
691 return false; 706 return false;
692 }, 707 },
693 708
694 /** 709 /**
695 * Finds slices intersecting the given interval. 710 * Adds items intersecting the given range to a selection.
696 * @param {number} loWX Lower X bound of the interval to search, in 711 * @param {number} loWX Lower X bound of the interval to search, in
697 * worldspace. 712 * worldspace.
698 * @param {number} hiWX Upper X bound of the interval to search, in 713 * @param {number} hiWX Upper X bound of the interval to search, in
699 * worldspace. 714 * worldspace.
700 * @param {number} loY Lower Y bound of the interval to search, in 715 * @param {number} loY Lower Y bound of the interval to search, in
701 * offset space. 716 * offset space.
702 * @param {number} hiY Upper Y bound of the interval to search, in 717 * @param {number} hiY Upper Y bound of the interval to search, in
703 * offset space. 718 * offset space.
704 * @param {function():*} onHitCallback Function to call for each slice 719 * @param {TimelineSelection} selection Selection to which to add hits.
705 * intersecting the interval.
706 */ 720 */
707 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 721 addIntersectingItemsInRangeToSelection: function(
722 loWX, hiWX, loY, hiY, selection) {
708 var clientRect = this.getBoundingClientRect(); 723 var clientRect = this.getBoundingClientRect();
709 var a = Math.max(loY, clientRect.top); 724 var a = Math.max(loY, clientRect.top);
710 var b = Math.min(hiY, clientRect.bottom); 725 var b = Math.min(hiY, clientRect.bottom);
711 if (a > b) 726 if (a > b)
712 return; 727 return;
713 728
714 var that = this; 729 var that = this;
715 function onPickHit(slice) { 730 function onPickHit(slice) {
716 onHitCallback('slice', that, slice); 731 var hit = selection.addSlice(that, slice);
732 that.decorateHit(hit);
717 } 733 }
718 tracing.iterateOverIntersectingIntervals(this.slices_, 734 tracing.iterateOverIntersectingIntervals(this.slices_,
719 function(x) { return x.start; }, 735 function(x) { return x.start; },
720 function(x) { return x.duration; }, 736 function(x) { return x.duration; },
721 loWX, hiWX, 737 loWX, hiWX,
722 onPickHit); 738 onPickHit);
723 }, 739 },
724 740
725 /** 741 /**
726 * Find the index for the given slice. 742 * Find the index for the given slice.
727 * @return {index} Index of the given slice, or undefined. 743 * @return {index} Index of the given slice, or undefined.
728 * @private 744 * @private
729 */ 745 */
730 indexOfSlice_: function(slice) { 746 indexOfSlice_: function(slice) {
731 var index = tracing.findLowIndexInSortedArray(this.slices_, 747 var index = tracing.findLowIndexInSortedArray(this.slices_,
732 function(x) { return x.start; }, 748 function(x) { return x.start; },
733 slice.start); 749 slice.start);
734 while (index < this.slices_.length && 750 while (index < this.slices_.length &&
735 slice.start == this.slices_[index].start && 751 slice.start == this.slices_[index].start &&
736 slice.colorId != this.slices_[index].colorId) { 752 slice.colorId != this.slices_[index].colorId) {
737 index++; 753 index++;
738 } 754 }
739 return index < this.slices_.length ? index : undefined; 755 return index < this.slices_.length ? index : undefined;
740 }, 756 },
741 757
742 /** 758 /**
743 * Return the next slice, if any, after the given slice. 759 * Add the item to the left or right of the provided hit, if any, to the
744 * @param {slice} The previous slice. 760 * selection.
745 * @return {slice} The next slice, or undefined. 761 * @param {slice} The current slice.
762 * @param {Number} offset Number of slices away from the hit to look.
763 * @param {TimelineSelection} selection The selection to add a hit to,
764 * if found.
765 * @return {boolean} Whether a hit was found.
746 * @private 766 * @private
747 */ 767 */
748 pickNext: function(slice) { 768 addItemNearToProvidedHitToSelection: function(hit, offset, selection) {
749 var index = this.indexOfSlice_(slice); 769 if (!hit.slice)
750 if (index != undefined) { 770 return false;
751 if (index < this.slices_.length - 1) 771
752 index++; 772 var index = this.indexOfSlice_(hit.slice);
753 else 773 if (index === undefined)
754 index = undefined; 774 return false;
755 } 775
756 return index != undefined ? this.slices_[index] : undefined; 776 var newIndex = index + offset;
777 if (newIndex < 0 || newIndex >= this.slices_.length)
778 return false;
779
780 var hit = selection.addSlice(this, this.slices_[newIndex]);
781 this.decorateHit(hit);
782 return true;
757 }, 783 },
758 784
759 /** 785 addAllObjectsMatchingFilterToSelection: function(filter, selection) {
760 * Return the previous slice, if any, before the given slice. 786 for (var i = 0; i < this.slices_.length; ++i) {
761 * @param {slice} A slice. 787 if (filter.matchSlice(this.slices_[i])) {
762 * @return {slice} The previous slice, or undefined. 788 var hit = selection.addSlice(this, this.slices_[i]);
763 */ 789 this.decorateHit(hit);
764 pickPrevious: function(slice) { 790 }
765 var index = this.indexOfSlice_(slice); 791 }
766 if (index == 0)
767 return undefined;
768 else if ((index != undefined) && (index > 0))
769 index--;
770 return index != undefined ? this.slices_[index] : undefined;
771 },
772
773 findAllObjectsMatchingFilter: function(filter) {
774 var hits = [];
775 for (var i = 0; i < this.slices_.length; ++i)
776 if (filter.matchSlice(this.slices_[i]))
777 hits.push({track: this,
778 slice: this.slices_[i]});
779 return hits;
780 } 792 }
781 }; 793 };
782 794
783 /** 795 /**
784 * A track that displays the viewport size and scale. 796 * A track that displays the viewport size and scale.
785 * @constructor 797 * @constructor
786 * @extends {CanvasBasedTrack} 798 * @extends {CanvasBasedTrack}
787 */ 799 */
788 800
789 var TimelineViewportTrack = cr.ui.define(CanvasBasedTrack); 801 var TimelineViewportTrack = cr.ui.define(CanvasBasedTrack);
790 802
791 var logOf10 = Math.log(10); 803 var logOf10 = Math.log(10);
792 function log10(x) { 804 function log10(x) {
793 return Math.log(x) / logOf10; 805 return Math.log(x) / logOf10;
794 } 806 }
795 807
796 TimelineViewportTrack.prototype = { 808 TimelineViewportTrack.prototype = {
797 809
798 __proto__: CanvasBasedTrack.prototype, 810 __proto__: CanvasBasedTrack.prototype,
799 811
800 decorate: function() { 812 decorate: function() {
813 CanvasBasedTrack.prototype.decorate.call(this);
801 this.classList.add('timeline-viewport-track'); 814 this.classList.add('timeline-viewport-track');
802 this.strings_secs_ = []; 815 this.strings_secs_ = [];
803 this.strings_msecs_ = []; 816 this.strings_msecs_ = [];
804 }, 817 },
805 818
806 redraw: function() { 819 redraw: function() {
807 var ctx = this.ctx_; 820 var ctx = this.ctx_;
808 var canvasW = this.canvas_.width; 821 var canvasW = this.canvas_.width;
809 var canvasH = this.canvas_.height; 822 var canvasH = this.canvas_.height;
810 823
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 var xView = Math.floor(curXView + minorMarkDistancePx * i); 902 var xView = Math.floor(curXView + minorMarkDistancePx * i);
890 ctx.moveTo(xView, canvasH - minorTickH); 903 ctx.moveTo(xView, canvasH - minorTickH);
891 ctx.lineTo(xView, canvasH); 904 ctx.lineTo(xView, canvasH);
892 } 905 }
893 906
894 ctx.stroke(); 907 ctx.stroke();
895 } 908 }
896 }, 909 },
897 910
898 /** 911 /**
899 * Picks a slice, if any, at a given location. 912 * Adds items intersecting a point to a selection.
900 * @param {number} wX X location to search at, in worldspace. 913 * @param {number} wX X location to search at, in worldspace.
901 * @param {number} wY Y location to search at, in offset space. 914 * @param {number} wY Y location to search at, in offset space.
902 * offset space. 915 * offset space.
903 * @param {function():*} onHitCallback Callback to call with the slice, 916 * @param {TimelineSelection} selection Selection to which to add hits.
904 * if one is found.
905 * @return {boolean} true if a slice was found, otherwise false. 917 * @return {boolean} true if a slice was found, otherwise false.
906 */ 918 */
907 pick: function(wX, wY, onHitCallback) { 919 addIntersectingItemsToSelection: function(wX, wY, selection) {
908 // Does nothing. There's nothing interesting to pick on the viewport 920 // Does nothing. There's nothing interesting to pick on the viewport
909 // track. 921 // track.
910 }, 922 },
911 923
912 /** 924 /**
913 * Finds slices intersecting the given interval. 925 * Adds items intersecting the given range to a selection.
914 * @param {number} loWX Lower X bound of the interval to search, in 926 * @param {number} loWX Lower X bound of the interval to search, in
915 * worldspace. 927 * worldspace.
916 * @param {number} hiWX Upper X bound of the interval to search, in 928 * @param {number} hiWX Upper X bound of the interval to search, in
917 * worldspace. 929 * worldspace.
918 * @param {number} loY Lower Y bound of the interval to search, in 930 * @param {number} loY Lower Y bound of the interval to search, in
919 * offset space. 931 * offset space.
920 * @param {number} hiY Upper Y bound of the interval to search, in 932 * @param {number} hiY Upper Y bound of the interval to search, in
921 * offset space. 933 * offset space.
922 * @param {function():*} onHitCallback Function to call for each slice 934 * @param {TimelineSelection} selection Selection to which to add hits.
923 * intersecting the interval.
924 */ 935 */
925 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 936 addIntersectingItemsInRangeToSelection: function(
937 loWX, hiWX, loY, hiY, selection) {
926 // Does nothing. There's nothing interesting to pick on the viewport 938 // Does nothing. There's nothing interesting to pick on the viewport
927 // track. 939 // track.
928 }, 940 },
929 941
930 findAllObjectsMatchingFilter: function(filter) { 942 addAllObjectsMatchingFilterToSelection: function(filter, selection) {
931 return [];
932 } 943 }
933 944
934 }; 945 };
935 946
936 /** 947 /**
937 * A track that displays a TimelineCounter object. 948 * A track that displays a TimelineCounter object.
938 * @constructor 949 * @constructor
939 * @extends {CanvasBasedTrack} 950 * @extends {CanvasBasedTrack}
940 */ 951 */
941 952
942 var TimelineCounterTrack = cr.ui.define(CanvasBasedTrack); 953 var TimelineCounterTrack = cr.ui.define(CanvasBasedTrack);
943 954
944 TimelineCounterTrack.prototype = { 955 TimelineCounterTrack.prototype = {
945 956
946 __proto__: CanvasBasedTrack.prototype, 957 __proto__: CanvasBasedTrack.prototype,
947 958
948 decorate: function() { 959 decorate: function() {
960 CanvasBasedTrack.prototype.decorate.call(this);
949 this.classList.add('timeline-counter-track'); 961 this.classList.add('timeline-counter-track');
950 addControlButtonElements(this, false); 962 addControlButtonElements(this, false);
963 this.selectedSamples_ = {};
964 },
965
966 /**
967 * Called by all the addToSelection functions on the created selection
968 * hit objects. Override this function on parent classes to add
969 * context-specific information to the hit.
970 */
971 decorateHit: function(hit) {
951 }, 972 },
952 973
953 get counter() { 974 get counter() {
954 return this.counter_; 975 return this.counter_;
955 }, 976 },
956 977
957 set counter(counter) { 978 set counter(counter) {
958 this.counter_ = counter; 979 this.counter_ = counter;
959 this.invalidate(); 980 this.invalidate();
960 }, 981 },
961 982
983 /**
984 * @return {Object} A sparce, mutable map from sample index to bool. Samples
985 * indices the map that are true are drawn as selected. Callers that mutate
986 * the map must manually call invalidate on the track to trigger a redraw.
987 */
988 get selectedSamples() {
989 return this.selectedSamples_;
990 },
991
962 redraw: function() { 992 redraw: function() {
963 var ctr = this.counter_; 993 var ctr = this.counter_;
964 var ctx = this.ctx_; 994 var ctx = this.ctx_;
965 var canvasW = this.canvas_.width; 995 var canvasW = this.canvas_.width;
966 var canvasH = this.canvas_.height; 996 var canvasH = this.canvas_.height;
967 997
968 ctx.clearRect(0, 0, canvasW, canvasH); 998 ctx.clearRect(0, 0, canvasW, canvasH);
969 999
970 // Culling parametrs. 1000 // Culling parametrs.
971 var vp = this.viewport_; 1001 var vp = this.viewport_;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 } 1069 }
1040 ctx.lineTo(x, yLastView); 1070 ctx.lineTo(x, yLastView);
1041 ctx.lineTo(x, yView); 1071 ctx.lineTo(x, yView);
1042 iLast = i; 1072 iLast = i;
1043 xLast = x; 1073 xLast = x;
1044 yLastView = yView; 1074 yLastView = yView;
1045 } 1075 }
1046 ctx.closePath(); 1076 ctx.closePath();
1047 ctx.fill(); 1077 ctx.fill();
1048 } 1078 }
1079 ctx.fillStyle = 'rgba(255, 0, 0, 1)';
1080 for (var i in this.selectedSamples_) {
1081 if (!this.selectedSamples_[i])
1082 continue;
1083
1084 var x = ctr.timestamps[i];
1085 for (var seriesIndex = ctr.numSeries - 1;
1086 seriesIndex >= 0; seriesIndex--) {
1087 var y = ctr.totals[i * numSeries + seriesIndex];
1088 var yView = canvasH - (yScale * y);
1089 ctx.fillRect(x - pixWidth, yView - 1, 3 * pixWidth, 3);
1090 }
1091 }
1049 ctx.restore(); 1092 ctx.restore();
1050 }, 1093 },
1051 1094
1052 /** 1095 /**
1053 * Picks a slice, if any, at a given location. 1096 * Adds items intersecting a point to a selection.
1054 * @param {number} wX X location to search at, in worldspace. 1097 * @param {number} wX X location to search at, in worldspace.
1055 * @param {number} wY Y location to search at, in offset space. 1098 * @param {number} wY Y location to search at, in offset space.
1056 * offset space. 1099 * offset space.
1057 * @param {function():*} onHitCallback Callback to call with the slice, 1100 * @param {TimelineSelection} selection Selection to which to add hits.
1058 * if one is found.
1059 * @return {boolean} true if a slice was found, otherwise false. 1101 * @return {boolean} true if a slice was found, otherwise false.
1060 */ 1102 */
1061 pick: function(wX, wY, onHitCallback) { 1103 addIntersectingItemsToSelection: function(wX, wY, selection) {
1104 var clientRect = this.getBoundingClientRect();
1105 if (wY < clientRect.top || wY >= clientRect.bottom)
1106 return false;
1107 var ctr = this.counter_;
1108 if (wX < this.counter_.timestamps[0])
1109 return false;
1110 var i = tracing.findLowIndexInSortedArray(ctr.timestamps,
1111 function(x) { return x; },
1112 wX);
1113 if (i < 0 || i >= ctr.timestamps.length)
1114 return false;
1115
1116 // Sample i is going to either be exactly at wX or slightly above it,
1117 // E.g. asking for 7.5 in [7,8] gives i=1. So bump i back by 1 if needed.
1118 if (i > 0 && wX > this.counter_.timestamps[i - 1])
1119 i--;
1120
1121 // Some preliminaries.
1122 var canvasH = this.getBoundingClientRect().height;
1123 var yScale = canvasH / ctr.maxTotal;
1124
1125 /*
1126 // Figure out which sample we hit
1127 var seriesIndexHit;
1128 for (var seriesIndex = 0; seriesIndex < ctr.numSeries; seriesIndex++) {
1129 var y = ctr.totals[i * ctr.numSeries + seriesIndex];
1130 var yView = canvasH - (yScale * y) + clientRect.top;
1131 if (wY >= yView) {
1132 seriesIndexHit = seriesIndex;
1133 break;
1134 }
1135 }
1136 if (seriesIndexHit === undefined)
1137 return false;
1138 */
1139 var hit = selection.addCounterSample(this, this.counter, i);
1140 this.decorateHit(hit);
1141 return true;
1062 }, 1142 },
1063 1143
1064 /** 1144 /**
1065 * Finds slices intersecting the given interval. 1145 * Adds items intersecting the given range to a selection.
1066 * @param {number} loWX Lower X bound of the interval to search, in 1146 * @param {number} loWX Lower X bound of the interval to search, in
1067 * worldspace. 1147 * worldspace.
1068 * @param {number} hiWX Upper X bound of the interval to search, in 1148 * @param {number} hiWX Upper X bound of the interval to search, in
1069 * worldspace. 1149 * worldspace.
1070 * @param {number} loY Lower Y bound of the interval to search, in 1150 * @param {number} loY Lower Y bound of the interval to search, in
1071 * offset space. 1151 * offset space.
1072 * @param {number} hiY Upper Y bound of the interval to search, in 1152 * @param {number} hiY Upper Y bound of the interval to search, in
1073 * offset space. 1153 * offset space.
1074 * @param {function():*} onHitCallback Function to call for each slice 1154 * @param {TimelineSelection} selection Selection to which to add hits.
1075 * intersecting the interval.
1076 */ 1155 */
1077 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 1156 addIntersectingItemsInRangeToSelection: function(
1157 loWX, hiWX, loY, hiY, selection) {
1158
1159 var clientRect = this.getBoundingClientRect();
1160 var a = Math.max(loY, clientRect.top);
1161 var b = Math.min(hiY, clientRect.bottom);
1162 if (a > b)
1163 return;
1164
1165 var ctr = this.counter_;
1166
1167 var iLo = tracing.findLowIndexInSortedArray(ctr.timestamps,
1168 function(x) { return x; },
1169 loWX);
1170 var iHi = tracing.findLowIndexInSortedArray(ctr.timestamps,
1171 function(x) { return x; },
1172 hiWX);
1173
1174 // Sample i is going to either be exactly at wX or slightly above it,
1175 // E.g. asking for 7.5 in [7,8] gives i=1. So bump i back by 1 if needed.
1176 if (iLo > 0 && loWX > ctr.timestamps[iLo - 1])
1177 iLo--;
1178 if (iHi > 0 && hiWX > ctr.timestamps[iHi - 1])
1179 iHi--;
1180
1181 // Iterate over every sample intersecting..
1182 for (var i = iLo; i <= iHi; i++) {
1183 if (i >= ctr.timestamps.length)
1184 continue;
1185
1186 // TODO(nduca): Pick the seriesIndexHit based on the loY - hiY values.
1187 var hit = selection.addCounterSample(this, this.counter, i);
1188 this.decorateHit(hit);
1189 }
1078 }, 1190 },
1079 1191
1080 findAllObjectsMatchingFilter: function(filter) { 1192 addAllObjectsMatchingFilterToSelection: function(filter, selection) {
1081 return [];
1082 } 1193 }
1083 1194
1084 }; 1195 };
1085 1196
1086 return { 1197 return {
1087 TimelineCounterTrack: TimelineCounterTrack, 1198 TimelineCounterTrack: TimelineCounterTrack,
1088 TimelineSliceTrack: TimelineSliceTrack, 1199 TimelineSliceTrack: TimelineSliceTrack,
1089 TimelineThreadTrack: TimelineThreadTrack, 1200 TimelineThreadTrack: TimelineThreadTrack,
1090 TimelineViewportTrack: TimelineViewportTrack, 1201 TimelineViewportTrack: TimelineViewportTrack,
1091 TimelineCpuTrack: TimelineCpuTrack 1202 TimelineCpuTrack: TimelineCpuTrack
1092 }; 1203 };
1093 }); 1204 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698