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

Side by Side Diff: runtime/observatory/lib/src/app/view_model.dart

Issue 2204563003: Converted Observatory cpu-profile element (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Removed tmp files Created 4 years, 4 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of app; 5 part of app;
6 6
7 abstract class VirtualTreeRow {
8 // Number of ems each subtree is indented.
9 static const subtreeIndent = 2.0;
10
11 static const redColor = '#F44336';
12 static const blueColor = '#3F51B5';
13 static const purpleColor = '#673AB7';
14 static const greenColor = '#4CAF50';
15 static const orangeColor = '#FF9800';
16 static const lightGrayColor = '#FAFAFA';
17
18 List backgroundColors = const [
19 purpleColor,
20 redColor,
21 greenColor,
22 blueColor,
23 orangeColor,
24 ];
25
26 final VirtualTree tree;
27 final List<VirtualTreeRow> children = [];
28 final List<StreamSubscription> _listeners = [];
29 final int depth;
30 bool _expanded = false;
31
32 VirtualTreeRow(this.tree, this.depth);
33
34 bool get expanded => _expanded;
35
36 set expanded(bool expanded) {
37 var changed = _expanded != expanded;
38 _expanded = expanded;
39 if (!changed) {
40 return;
41 }
42 if (_expanded) {
43 _expand();
44 } else {
45 _collapse();
46 }
47 }
48
49 Element makeColorBar(int depth) {
50 var element = new SpanElement();
51 element.style.paddingLeft = '2px';
52 element.style.paddingRight = '2px';
53 element.style.flexBasis = '2px';
54 element.style.height = '${tree.rowHeight}px';
55 element.style.minHeight = '${tree.rowHeight}px';
56 if (depth > 0) {
57 var colorIndex = (depth - 1) % backgroundColors.length;
58 element.style.backgroundColor = backgroundColors[colorIndex];
59 }
60 return element;
61 }
62
63 Element makeExpander() {
64 SpanElement element = new SpanElement();
65 element.style.flexBasis = '2em';
66 if (!hasChildren()) {
67 element.style.visibility = 'hidden';
68 } else {
69 element.style.visibility = 'visible';
70 element.children.add(expanded ?
71 new Element.tag('icon-expand-more') :
72 new Element.tag('icon-chevron-right'));
73 }
74 _listeners.add(element.onClick.listen((e) {
75 e.stopPropagation();
76 toggle();
77 }));
78 return element;
79 }
80
81 Element makeIndenter(int depth, {colored: true}) {
82 SpanElement element = new SpanElement();
83 element.style.paddingLeft = '${subtreeIndent * depth}em';
84 element.style.flexBasis = '${subtreeIndent * depth}em';
85 element.style.height = '${tree.rowHeight}px';
86 element.style.minHeight = '${tree.rowHeight}px';
87 if (colored) {
88 if (depth > 0) {
89 var colorIndex = (depth - 1) % backgroundColors.length;
90 element.style.backgroundColor = backgroundColors[colorIndex];
91 }
92 }
93 return element;
94 }
95
96 Element makeText(String text, {String toolTip,
97 String flexBasis: '4.5em',
98 String cssClass}) {
99 SpanElement element = new SpanElement();
100 element.text = text;
101 if (toolTip != null) {
102 element.title = toolTip;
103 }
104 if (flexBasis != null) {
105 element.style.flexBasis = flexBasis;
106 }
107 if (cssClass != null) {
108 element.classes.add(cssClass);
109 }
110 return element;
111 }
112
113 Element makeGap({double ems: 0.5}) {
114 SpanElement element = new SpanElement();
115 var flexBasis = '${ems}em';
116 element.style.flexBasis = flexBasis;
117 return element;
118 }
119
120 void _cleanupListeners() {
121 for (var listener in _listeners) {
122 listener.cancel();
123 }
124 _listeners.clear();
125 }
126
127 void _expand() {
128 onShow();
129 tree._onExpand(this);
130 if (children.length == 1) {
131 children[0]._expand();
132 }
133 _expanded = true;
134 }
135
136 void _collapse() {
137 _expanded = false;
138 for (var i = 0; i < children.length; i++) {
139 if (children[i].expanded) {
140 children[i]._collapse();
141 }
142 }
143 tree._onCollapse(this);
144 }
145
146 void toggle() {
147 expanded = !expanded;
148 }
149
150 void _render(DivElement rowDiv) {
151 rowDiv.style.display = 'flex';
152 rowDiv.style.alignItems = 'center';
153 _cleanupListeners();
154 onShow();
155 onRender(rowDiv);
156 }
157
158 /// Called when you should render into [rowDiv].
159 void onRender(DivElement rowDiv);
160
161 // Called when this row is visible.
162 void onShow();
163
164 // Return the number of children this node has.
165 int get childCount => 0;
166
167 // Return true if this node can be expanded.
168 bool hasChildren() => childCount > 0;
169
170 // Called when this row is not visible.
171 void onHide() {
172 _cleanupListeners();
173 }
174 }
175
176 class VirtualTree {
177 final int rowHeight;
178 final List<VirtualTreeRow> rows = [];
179 final DivElement root;
180 final Stopwatch _clock = new Stopwatch();
181
182 DivElement _treeHeightElement;
183 DivElement _tree;
184
185 StreamSubscription _scrollSubscription;
186 StreamSubscription _resizeSubscription;
187
188 // Height of [root] in pixels.
189 int viewHeight;
190
191 // Number of pixels view can be scrolled before a redraw occurs.
192 int redrawThresholdPixels;
193
194 // Number of rows visible at any given time.
195 int numVisibleRows;
196 // Number of rows above the current view that are in the dom.
197 int extraRowsAbove;
198 // Number of rows below the current view that are in the dom.
199 int extraRowsBelow;
200
201 // The scroll top of the last scroll event.
202 int lastPaintScrollTop;
203
204 // The starting row of the last paint.
205 int lastPaintStartingRow = 0;
206
207 bool paintScheduled = false;
208
209 bool scrolled = false;
210
211 static const scrollStopThresholdMilliseconds = 100;
212
213 VirtualTree(this.rowHeight, this.root) {
214 _clock.start();
215 _install();
216 _resize();
217 _schedulePaint(0);
218 }
219
220 void uninstall() => _uninstall();
221
222 void refresh() {
223 _resize();
224 _schedulePaint(lastPaintStartingRow);
225 }
226
227 // Clear the tree.
228 void clear() {
229 rows.clear();
230 _resize();
231 }
232
233 void _onExpand(VirtualTreeRow parent) {
234 int index = rows.indexOf(parent);
235 if (index == -1) {
236 return;
237 }
238 rows.insertAll(index + 1, parent.children);
239 refresh();
240 }
241
242 void _onCollapse(VirtualTreeRow parent) {
243 int index = rows.indexOf(parent);
244 if (index == -1) {
245 return;
246 }
247 int start = index + 1;
248 int end = start + parent.children.length;
249 rows.removeRange(start, end);
250 refresh();
251 }
252
253 void _resize() {
254 if (viewHeight != root.offsetHeight) {
255 viewHeight = root.offsetHeight;
256 numVisibleRows = (viewHeight ~/ rowHeight) + 1;
257 extraRowsAbove = numVisibleRows ~/ 2;
258 extraRowsBelow = numVisibleRows - extraRowsAbove;
259 redrawThresholdPixels =
260 math.min(extraRowsAbove, extraRowsBelow) * rowHeight;
261 }
262 _treeHeightElement.style.height = '${_treeHeight()}px';
263 }
264
265 int _treeHeight() {
266 return rows.length * rowHeight;
267 }
268
269 int _pixelsFromLastScroll(int currentScrollTop) {
270 if (lastPaintScrollTop == null) {
271 return currentScrollTop;
272 }
273
274 return (currentScrollTop - lastPaintScrollTop).abs();
275 }
276
277 int _pixelToRow(int pixelY) {
278 int result = pixelY ~/ rowHeight;
279 return result;
280 }
281
282 void _install() {
283 // This element controls the height of the tree's scrollable region.
284 // It is one pixel wide and the height is set to rowHeight * numRows.
285 _treeHeightElement = new DivElement();
286 _treeHeightElement.style.position = 'absolute';
287 _treeHeightElement.style.top = '0';
288 _treeHeightElement.style.left = '0';
289 _treeHeightElement.style.width = '1px';
290
291 // This element holds the visible tree rows and the height controlling
292 // element. It takes the full width and height of its parent element.
293 _tree = new DivElement();
294 _tree.children.add(_treeHeightElement);
295 _tree.style.width = '100%';
296 _tree.style.height = '100%';
297 _tree.style.position = 'relative';
298 _tree.style.overflow = 'auto';
299
300 // Listen for scroll events on the tree.
301 _scrollSubscription = _tree.onScroll.listen(_onScroll);
302
303 root.children.add(_tree);
304
305 // Listen for resize events.
306 _resizeSubscription = window.onResize.listen((_) {
307 _resize();
308 _schedulePaint(lastPaintStartingRow);
309 });
310 }
311
312 void _uninstall() {
313 root.children.clear();
314 _scrollSubscription?.cancel();
315 _scrollSubscription = null;
316 _resizeSubscription?.cancel();
317 _resizeSubscription = null;
318 }
319
320 void _onScroll(Event scrollEvent) {
321 Element target = scrollEvent.target;
322 int scrollTop = target.scrollTop;
323 if (_pixelsFromLastScroll(scrollTop) > redrawThresholdPixels) {
324 _schedulePaint(lastPaintStartingRow);
325 scrolled = true;
326 }
327 scrollEvent.preventDefault();
328 }
329
330 void _schedulePaint(int startingRow) {
331 if (paintScheduled) {
332 return;
333 }
334 paintScheduled = true;
335 window.requestAnimationFrame(
336 (timestamp) => _onRenderFrame(timestamp, startingRow));
337 }
338
339 void _onRenderFrame(int timestamp, int startingRow) {
340 paintScheduled = false;
341 _paint(startingRow);
342 }
343
344 void _paint(int startingRow) {
345 if (scrolled) {
346 startingRow = math.max(_pixelToRow(_tree.scrollTop), 0);
347 scrolled = false;
348 }
349 lastPaintScrollTop = _tree.scrollTop;
350 lastPaintStartingRow = startingRow;
351
352 int endingRow =
353 math.min(rows.length, startingRow + numVisibleRows + extraRowsBelow);
354
355 startingRow =
356 math.max(0, startingRow - extraRowsAbove);
357
358 print('PAINT $startingRow $endingRow');
359
360 for (int i = startingRow; i < endingRow; i++) {
361 // We add 1 because _tree.children[0] contains the height control element.
362 int cacheIndex = (i - startingRow) + 1;
363 DivElement row;
364 if (cacheIndex < _tree.children.length) {
365 // re-use existing row.
366 row = _tree.children[cacheIndex];
367 row.children.clear();
368 } else {
369 // Allocate a new row.
370 row = new DivElement();
371 row.style.position = 'absolute';
372 row.style.height = '${rowHeight}px';
373 row.style.maxHeight = '${rowHeight}px';
374 row.style.margin = '0';
375 row.style.width = '100%';
376 row.style.left = '0';
377 _tree.children.add(row);
378 }
379 row.style.top = '${(i * rowHeight)}px';
380 // Render the row.
381 rows[i]._render(row);
382 }
383 int necessaryChildren = (endingRow - startingRow) + 1;
384 while (_tree.children.length > necessaryChildren) {
385 _tree.children.removeLast();
386 }
387 }
388 }
389
390 abstract class TableTreeRow extends Observable { 7 abstract class TableTreeRow extends Observable {
391 static const arrowRight = '\u2192'; 8 static const arrowRight = '\u2192';
392 static const arrowDownRight = '\u21b3'; 9 static const arrowDownRight = '\u21b3';
393 // Number of ems each subtree is indented. 10 // Number of ems each subtree is indented.
394 static const subtreeIndent = 2; 11 static const subtreeIndent = 2;
395 12
396 TableTreeRow(this.tree, TableTreeRow parent) : 13 TableTreeRow(this.tree, TableTreeRow parent) :
397 parent = parent, 14 parent = parent,
398 depth = parent != null ? parent.depth + 1 : 0 { 15 depth = parent != null ? parent.depth + 1 : 0 {
399 } 16 }
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 if (column != _sortColumnIndex) { 363 if (column != _sortColumnIndex) {
747 return columns[column].label + '\u2003'; 364 return columns[column].label + '\u2003';
748 } 365 }
749 return columns[column].label + (_sortDescending ? arrowUp : arrowDown); 366 return columns[column].label + (_sortDescending ? arrowUp : arrowDown);
750 } 367 }
751 368
752 dynamic getValue(int row, int column) { 369 dynamic getValue(int row, int column) {
753 return rows[row].values[column]; 370 return rows[row].values[column];
754 } 371 }
755 } 372 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698