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

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

Issue 965593002: Improved profiler view and inclusive profile tree (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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
« no previous file with comments | « no previous file | runtime/observatory/lib/src/cpu_profile/cpu_profile.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 TableTreeRow extends Observable { 7 abstract class TableTreeRow extends Observable {
8 static const arrowRight = '\u2192'; 8 static const arrowRight = '\u2192';
9 static const arrowDownRight = '\u21b3'; 9 static const arrowDownRight = '\u21b3';
10 // Number of pixels each subtree is indented. 10 // Number of ems each subtree is indented.
11 static const subtreeIndent = 16; 11 static const subtreeIndent = 2;
12
13 TableTreeRow(this.tree, TableTreeRow parent) :
14 parent = parent,
15 depth = parent != null ? parent.depth + 1 : 0 {
16 }
12 17
13 final TableTree tree; 18 final TableTree tree;
14 final TableTreeRow parent; 19 final TableTreeRow parent;
15 final int depth; 20 final int depth;
16 final List<TableTreeRow> children = new List<TableTreeRow>(); 21 final List<TableTreeRow> children = new List<TableTreeRow>();
17 final List<TableCellElement> tableColumns = new List<TableCellElement>(); 22 final List<TableCellElement> _tableColumns = new List<TableCellElement>();
23 final List<DivElement> flexColumns = new List<DivElement>();
18 SpanElement _expander; 24 SpanElement _expander;
19 TableRowElement _tr; 25 TableRowElement _tr;
20 TableRowElement get tr { 26 TableRowElement get tr => _tr;
21 assert(_tr != null);
22 return _tr;
23 }
24
25 TableTreeRow(this.tree, TableTreeRow parent) :
26 parent = parent,
27 depth = parent != null ? parent.depth+1 : 0 {
28 }
29
30 bool _expanded = false; 27 bool _expanded = false;
31 bool get expanded => _expanded; 28 bool get expanded => _expanded;
32 set expanded(bool expanded) { 29 set expanded(bool expanded) {
33 var changed = _expanded != expanded; 30 var changed = _expanded != expanded;
34 _expanded = expanded; 31 _expanded = expanded;
35 if (changed) { 32 if (changed) {
36 // If the state has changed, fire callbacks. 33 // If the state has changed, fire callbacks.
37 if (_expanded) { 34 if (_expanded) {
38 _onExpand(); 35 _onExpand();
39 } else { 36 } else {
40 _onCollapse(); 37 _onCollapse();
41 } 38 }
42 } 39 }
43 } 40 }
44 41
45 bool expandOrCollapse() { 42 /// Fired when the tree row is being expanded.
43 void _onExpand() {
44 _updateExpanderView();
45 }
46
47 /// Fired when the tree row is being collapsed.
48 void _onCollapse() {
49 for (var child in children) {
50 child.onHide();
51 }
52 _updateExpanderView();
53 }
54
55 bool toggle() {
46 expanded = !expanded; 56 expanded = !expanded;
47 return expanded; 57 return expanded;
48 } 58 }
49 59
50 bool hasChildren(); 60 HtmlElement _makeColorBlock(String backgroundColor) {
51 61 var colorBlock = new DivElement();
52 String _backgroundColorClassForRow() { 62 colorBlock.style.minWidth = '2px';
53 const colors = const ['rowColor0', 'rowColor1', 'rowColor2', 'rowColor3', 63 colorBlock.style.backgroundColor = backgroundColor;
54 'rowColor4', 'rowColor5', 'rowColor6', 'rowColor7', 64 return colorBlock;
55 'rowColor8'];
56 var index = (depth - 1) % colors.length;
57 return colors[index];
58 } 65 }
59 66
67 HtmlElement _makeExpander() {
68 var expander = new SpanElement();
69 expander.style.minWidth = '1.5em';
70 expander.onClick.listen(onClick);
71 return expander;
72 }
73
74 void onClick(Event e) {
75 e.stopPropagation();
76 tree.toggle(this);
77 }
78
79 static const redColor = '#F44336';
80 static const blueColor = '#3F51B5';
81 static const purpleColor = '#673AB7';
82 static const greenColor = '#4CAF50';
83 static const orangeColor = '#FF9800';
84 static const lightGrayColor = '#FAFAFA';
85
60 void _buildRow() { 86 void _buildRow() {
87 const List backgroundColors = const [
88 purpleColor,
89 redColor,
90 greenColor,
91 blueColor,
92 orangeColor,
93 ];
61 _tr = new TableRowElement(); 94 _tr = new TableRowElement();
62 for (var i = 0; i < tree.columnCount; i++) { 95 for (var i = 0; i < tree.columnCount; i++) {
63 var cell = _tr.insertCell(-1); 96 var cell = _tr.insertCell(-1);
64 cell.classes.add(_backgroundColorClassForRow()); 97 _tableColumns.add(cell);
65 tableColumns.add(cell); 98 var flex = new DivElement();
99 flex.classes.add('flex-row');
100 cell.children.add(flex);
101 flexColumns.add(flex);
66 } 102 }
67 var firstColumn = tableColumns[0]; 103 var firstColumn = flexColumns[0];
68 var columnContainer = new DivElement(); 104 _tableColumns[0].style.paddingLeft = '${(depth - 1) * subtreeIndent}em';
69 columnContainer.classes.add('flex-row'); 105 var backgroundColor = lightGrayColor;
70 _expander = new SpanElement(); 106 if (depth > 1) {
71 _expander.style.display = 'inline-block'; 107 var colorIndex = (depth - 1) % backgroundColors.length;
72 _expander.style.display = 'inline-block'; 108 backgroundColor = backgroundColors[colorIndex];
73 _expander.style.minWidth = '1.5em'; 109 }
74 _expander.onClick.listen(onClick); 110 var colorBlock = _makeColorBlock(backgroundColor);
75 columnContainer.children.add(_expander); 111 firstColumn.children.add(colorBlock);
76 firstColumn.style.paddingLeft = '${depth * subtreeIndent}px'; 112 _expander = _makeExpander();
77 firstColumn.children.add(columnContainer); 113 firstColumn.children.add(_expander);
78 updateExpanderView(); 114 // Enable expansion by clicking anywhere on the first column.
115 firstColumn.onClick.listen(onClick);
116 _updateExpanderView();
79 } 117 }
80 118
81 void updateExpanderView() { 119 void _updateExpanderView() {
82 if (_expander == null) { 120 if (_expander == null) {
83 return; 121 return;
84 } 122 }
85 if (!hasChildren()) { 123 if (!hasChildren()) {
86 _expander.style.visibility = 'hidden'; 124 _expander.style.visibility = 'hidden';
87 _expander.style.cursor = 'auto'; 125 _expander.classes.remove('pointer');
88 return; 126 return;
89 } else { 127 } else {
90 _expander.style.visibility = 'visible'; 128 _expander.style.visibility = 'visible';
91 _expander.style.cursor = 'pointer'; 129 _expander.classes.add('pointer');
92 } 130 }
93 _expander.text = expanded ? arrowDownRight : arrowRight; 131 _expander.children.clear();
132 _expander.children.add(expanded ?
133 new Element.tag('icon-expand-more') :
134 new Element.tag('icon-chevron-right'));
94 } 135 }
95 136
137 bool hasChildren();
138
96 /// Fired when the tree row is being shown. 139 /// Fired when the tree row is being shown.
97 /// Populate tr and add logical children here. 140 /// Populate tr and add logical children here.
98 void onShow() { 141 void onShow() {
99 assert(_tr == null); 142 assert(_tr == null);
100 _buildRow(); 143 _buildRow();
101 } 144 }
102 145
103 /// Fired when the tree row is being hidden. 146 /// Fired when the tree row is being hidden.
104 void onHide() { 147 void onHide() {
105 assert(_tr != null);
106 _tr = null; 148 _tr = null;
107 tableColumns.clear();
108 _expander = null; 149 _expander = null;
109 } 150 if (_tableColumns != null) {
110 151 _tableColumns.clear();
111 /// Fired when the tree row is being expanded.
112 void _onExpand() {
113 for (var child in children) {
114 child.onShow();
115 child.updateExpanderView();
116 } 152 }
117 updateExpanderView(); 153 if (flexColumns != null) {
118 } 154 flexColumns.clear();
119
120 /// Fired when the tree row is being collapsed.
121 void _onCollapse() {
122 for (var child in children) {
123 child.onHide();
124 } 155 }
125 updateExpanderView();
126 }
127
128 void onClick(Event e) {
129 tree.toggle(this);
130 e.stopPropagation();
131 } 156 }
132 } 157 }
133 158
134 class TableTree extends Observable { 159 class TableTree extends Observable {
135 final TableSectionElement tableBody; 160 final TableSectionElement tableBody;
136 final List<TableTreeRow> rows = []; 161 final List<TableTreeRow> rows = [];
137 final int columnCount; 162 final int columnCount;
138 163 Future _pendingOperation;
139 /// Create a table tree with column [headers]. 164 /// Create a table tree with column [headers].
140 TableTree(this.tableBody, this.columnCount); 165 TableTree(this.tableBody, this.columnCount);
141 166
142 void clear() { 167 void clear() {
143 tableBody.children.clear(); 168 tableBody.children.clear();
144 rows.clear(); 169 rows.clear();
145 } 170 }
146 171
147 /// Initialize the table tree with the list of root children. 172 /// Initialize the table tree with the list of root children.
148 void initialize(TableTreeRow root) { 173 void initialize(TableTreeRow root) {
149 clear(); 174 clear();
150 root.onShow(); 175 root.onShow();
151 rows.addAll(root.children); 176 toggle(root);
152 for (var i = 0; i < rows.length; i++) {
153 rows[i].onShow();
154 tableBody.children.add(rows[i].tr);
155 }
156 } 177 }
157 178
158 /// Toggle expansion of row in tree. 179 /// Toggle expansion of row in tree.
159 void toggle(TableTreeRow row) { 180 toggle(TableTreeRow row) async {
160 if (row.expandOrCollapse()) { 181 if (_pendingOperation != null) {
161 _expand(row); 182 return;
183 }
184 if (row.toggle()) {
185 document.body.classes.add('busy');
186 _pendingOperation = _expand(row);
187 await _pendingOperation;
188 _pendingOperation = null;
189 document.body.classes.remove('busy');
190 if (row.children.length == 1) {
191 // Auto expand single child.
192 await toggle(row.children[0]);
193 }
162 } else { 194 } else {
163 _collapse(row); 195 document.body.classes.add('busy');
196 _pendingOperation = _collapse(row);
197 await _pendingOperation;
198 _pendingOperation = null;
199 document.body.classes.remove('busy');
164 } 200 }
165 } 201 }
166 202
167 int _index(TableTreeRow row) => rows.indexOf(row); 203 int _index(TableTreeRow row) => rows.indexOf(row);
168 204
169 void _expand(TableTreeRow row) { 205 _insertRow(index, child) {
206 rows.insert(index, child);
207 tableBody.children.insert(index, child.tr);
208 }
209
210 _expand(TableTreeRow row) async {
170 int index = _index(row); 211 int index = _index(row);
171 assert(index != -1); 212 if ((index == -1) && (rows.length != 0)) {
172 rows.insertAll(index + 1, row.children); 213 return;
173 for (var i = 0; i < row.children.length; i++) { 214 }
174 tableBody.children.insert(index + i + 1, row.children[i].tr); 215 assert((index != -1) || (rows.length == 0));
216 var i = 0;
217 var addPerIteration = 10;
218 while (i < row.children.length) {
219 await window.animationFrame;
220 for (var j = 0; j < addPerIteration; j++) {
221 if (i == row.children.length) {
222 break;
223 }
224 var child = row.children[i];
225 child.onShow();
226 child._updateExpanderView();
227 _insertRow(index + i + 1, child);
228 i++;
229 }
175 } 230 }
176 } 231 }
177 232
178 void _collapse(TableTreeRow row) { 233 _collapseSync(TableTreeRow row) {
179 var childCount = row.children.length; 234 var childCount = row.children.length;
180 if (childCount == 0) { 235 if (childCount == 0) {
181 return; 236 return;
182 } 237 }
183 for (var i = 0; i < childCount; i++) { 238 for (var i = 0; i < childCount; i++) {
184 // Close all inner rows. 239 // Close all inner rows.
185 if (row.children[i].expanded) { 240 if (row.children[i].expanded) {
186 _collapse(row.children[i]); 241 _collapseSync(row.children[i]);
187 } 242 }
188 } 243 }
189 // Collapse this row. 244 // Collapse this row.
190 row.expanded = false; 245 row.expanded = false;
191 // Remove all children. 246 // Remove all children.
192 int index = _index(row); 247 int index = _index(row);
193 rows.removeRange(index + 1, index + 1 + childCount);
194 for (var i = 0; i < childCount; i++) { 248 for (var i = 0; i < childCount; i++) {
249 rows.removeAt(index + 1);
195 tableBody.children.removeAt(index + 1); 250 tableBody.children.removeAt(index + 1);
196 } 251 }
197 } 252 }
253
254 _collapse(TableTreeRow row) async {
255 _collapseSync(row);
256 }
198 } 257 }
199 258
200 typedef String ValueFormatter(dynamic value); 259 typedef String ValueFormatter(dynamic value);
201 260
202 class SortedTableColumn { 261 class SortedTableColumn {
203 static String toStringFormatter(dynamic v) { 262 static String toStringFormatter(dynamic v) {
204 return v != null ? v.toString() : '<null>'; 263 return v != null ? v.toString() : '<null>';
205 } 264 }
206 final String label; 265 final String label;
207 final ValueFormatter formatter; 266 final ValueFormatter formatter;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 if (column != _sortColumnIndex) { 349 if (column != _sortColumnIndex) {
291 return columns[column].label + '\u2003'; 350 return columns[column].label + '\u2003';
292 } 351 }
293 return columns[column].label + (_sortDescending ? arrowUp : arrowDown); 352 return columns[column].label + (_sortDescending ? arrowUp : arrowDown);
294 } 353 }
295 354
296 dynamic getValue(int row, int column) { 355 dynamic getValue(int row, int column) {
297 return rows[row].values[column]; 356 return rows[row].values[column];
298 } 357 }
299 } 358 }
OLDNEW
« no previous file with comments | « no previous file | runtime/observatory/lib/src/cpu_profile/cpu_profile.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698