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

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

Issue 839633004: Improve performance of table trees by around 3x (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 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) 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 final TableTreeRow parent;
9 @observable final int depth;
10 @observable final List<TableTreeRow> children = new List<TableTreeRow>();
11 @observable final List<String> columns = [];
12 static const arrowRight = '\u2192'; 8 static const arrowRight = '\u2192';
13 static const arrowDownRight = '\u21b3'; 9 static const arrowDownRight = '\u21b3';
14 static const showExpanderStyle = 'cursor: pointer;'; 10 // Number of pixels each subtree is indented.
15 static const hideExpanderStyle = 'visibility:hidden;'; 11 static const subtreeIndent = 16;
16 12
17 // TODO(johnmccutchan): Move expander display decisions into html once 13 final TableTree tree;
18 // tables and templates are better supported. 14 final TableTreeRow parent;
19 @observable String expander = arrowRight; 15 final int depth;
20 @observable String expanderStyle = showExpanderStyle; 16 final List<TableTreeRow> children = new List<TableTreeRow>();
17 final List<TableCellElement> tableColumns = new List<TableCellElement>();
18 SpanElement _expander;
19 TableRowElement _tr;
20 TableRowElement get tr {
21 assert(_tr != null);
22 return _tr;
23 }
21 24
22 TableTreeRow(TableTreeRow parent) : 25 TableTreeRow(this.tree, TableTreeRow parent) :
23 parent = parent, 26 parent = parent,
24 depth = parent != null ? parent.depth+1 : 0 { 27 depth = parent != null ? parent.depth+1 : 0 {
25 if (!hasChildren()) {
26 expanderStyle = hideExpanderStyle;
27 }
28 } 28 }
29 29
30 bool _expanded = false; 30 bool _expanded = false;
31 bool get expanded => _expanded; 31 bool get expanded => _expanded;
32 set expanded(bool expanded) { 32 set expanded(bool expanded) {
33 var changed = _expanded != expanded; 33 var changed = _expanded != expanded;
34 _expanded = expanded; 34 _expanded = expanded;
35 if (changed) { 35 if (changed) {
36 // If the state has changed, fire callbacks. 36 // If the state has changed, fire callbacks.
37 if (_expanded) { 37 if (_expanded) {
38 expander = arrowDownRight; 38 _onExpand();
39 onShow();
40 } else { 39 } else {
41 expander = arrowRight; 40 _onCollapse();
42 onHide();
43 } 41 }
44 } 42 }
45 } 43 }
46 44
47 bool toggle() { 45 bool expandOrCollapse() {
48 expanded = !expanded; 46 expanded = !expanded;
49 return expanded; 47 return expanded;
50 } 48 }
51 49
52 bool hasChildren(); 50 bool hasChildren();
53 51
54 /// Fired when the tree row is expanded. Add children rows here. 52 String _colorForRow() {
rmacnak 2015/01/09 21:55:50 classForRow?
Cutch 2015/01/09 22:00:42 backgroundColorClassForRow
55 void onShow(); 53 const colors = const ['rowColor0', 'rowColor1', 'rowColor2', 'rowColor3',
54 'rowColor4', 'rowColor5', 'rowColor6', 'rowColor7',
55 'rowColor8'];
56 var index = (depth - 1) % colors.length;
57 return colors[index];
58 }
56 59
57 /// Fired when the tree row is collapsed. 60 void _buildRow() {
58 void onHide(); 61 _tr = new TableRowElement();
62 for (var i = 0; i < tree.columnCount; i++) {
63 var cell = _tr.insertCell(-1);
64 cell.classes.add(_colorForRow());
65 tableColumns.add(cell);
66 }
67 var firstColumn = tableColumns[0];
68 _expander = new SpanElement();
69 _expander.style.display = 'inline-block';
70 _expander.style.minWidth = '1.5em';
71 _expander.onClick.listen(onClick);
72 firstColumn.children.add(_expander);
73 firstColumn.style.paddingLeft = '${depth * subtreeIndent}px';
74 updateExpanderView();
75 }
76
77 void updateExpanderView() {
78 if (_expander == null) {
79 return;
80 }
81 if (!hasChildren()) {
82 _expander.style.visibility = 'hidden';
83 _expander.style.cursor = 'auto';
84 return;
85 } else {
86 _expander.style.visibility = 'visible';
87 _expander.style.cursor = 'pointer';
88 }
89 _expander.text = expanded ? arrowDownRight : arrowRight;
90 }
91
92 /// Fired when the tree row is being shown.
93 /// Populate tr and add logical children here.
94 void onShow() {
95 assert(_tr == null);
96 _buildRow();
97 }
98
99 /// Fired when the tree row is being hidden.
100 void onHide() {
101 assert(_tr != null);
102 _tr = null;
103 tableColumns.clear();
104 _expander = null;
105 }
106
107 /// Fired when the tree row is being expanded.
108 void _onExpand() {
109 for (var child in children) {
110 child.onShow();
111 child.updateExpanderView();
112 }
113 updateExpanderView();
114 }
115
116 /// Fired when the tree row is being collapsed.
117 void _onCollapse() {
118 for (var child in children) {
119 child.onHide();
120 }
121 updateExpanderView();
122 }
123
124 void onClick(Event e) {
125 tree.toggle(this);
126 e.stopPropagation();
127 }
59 } 128 }
60 129
61 class TableTree extends Observable { 130 class TableTree extends Observable {
62 @observable final List<TableTreeRow> rows = toObservable([]); 131 final TableSectionElement tableBody;
132 final List<TableTreeRow> rows = [];
133 final int columnCount;
63 134
64 /// Create a table tree with column [headers]. 135 /// Create a table tree with column [headers].
65 TableTree(); 136 TableTree(this.tableBody, this.columnCount);
66 137
67 /// Initialize the table tree with the list of root children. 138 /// Initialize the table tree with the list of root children.
68 void initialize(TableTreeRow root) { 139 void initialize(TableTreeRow root) {
140 tableBody.children.clear();
69 rows.clear(); 141 rows.clear();
70 root.onShow(); 142 root.onShow();
71 rows.addAll(root.children); 143 rows.addAll(root.children);
144 for (var i = 0; i < rows.length; i++) {
145 rows[i].onShow();
146 tableBody.children.add(rows[i].tr);
147 }
72 } 148 }
73 149
74 /// Toggle expansion of row at [rowIndex]. 150 /// Toggle expansion of row in tree.
75 void toggle(int rowIndex) { 151 void toggle(TableTreeRow row) {
76 assert(rowIndex >= 0); 152 if (row.expandOrCollapse()) {
77 assert(rowIndex < rows.length);
78 var row = rows[rowIndex];
79 if (row.toggle()) {
80 _expand(row); 153 _expand(row);
81 } else { 154 } else {
82 _collapse(row); 155 _collapse(row);
83 } 156 }
84 } 157 }
85 158
86 int _index(TableTreeRow row) => rows.indexOf(row); 159 int _index(TableTreeRow row) => rows.indexOf(row);
87 160
88 void _expand(TableTreeRow row) { 161 void _expand(TableTreeRow row) {
89 int index = _index(row); 162 int index = _index(row);
90 assert(index != -1); 163 assert(index != -1);
91 rows.insertAll(index + 1, row.children); 164 rows.insertAll(index + 1, row.children);
165 for (var i = 0; i < row.children.length; i++) {
166 tableBody.children.insert(index + i + 1, row.children[i].tr);
167 }
92 } 168 }
93 169
94 void _collapse(TableTreeRow row) { 170 void _collapse(TableTreeRow row) {
95 var childCount = row.children.length; 171 var childCount = row.children.length;
96 if (childCount == 0) { 172 if (childCount == 0) {
97 return; 173 return;
98 } 174 }
99 for (var i = 0; i < childCount; i++) { 175 for (var i = 0; i < childCount; i++) {
100 // Close all inner rows. 176 // Close all inner rows.
101 if (row.children[i].expanded) { 177 if (row.children[i].expanded) {
102 _collapse(row.children[i]); 178 _collapse(row.children[i]);
103 } 179 }
104 } 180 }
105 // Collapse this row. 181 // Collapse this row.
106 row.expanded = false; 182 row.expanded = false;
107 // Remove all children. 183 // Remove all children.
108 int index = _index(row); 184 int index = _index(row);
109 rows.removeRange(index + 1, index + 1 + childCount); 185 rows.removeRange(index + 1, index + 1 + childCount);
186 for (var i = 0; i < childCount; i++) {
187 tableBody.children.removeAt(index + 1);
188 }
110 } 189 }
111 } 190 }
112 191
113 typedef String ValueFormatter(dynamic value); 192 typedef String ValueFormatter(dynamic value);
114 193
115 class SortedTableColumn { 194 class SortedTableColumn {
116 static String toStringFormatter(dynamic v) { 195 static String toStringFormatter(dynamic v) {
117 return v != null ? v.toString() : '<null>'; 196 return v != null ? v.toString() : '<null>';
118 } 197 }
119 final String label; 198 final String label;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 if (column != _sortColumnIndex) { 283 if (column != _sortColumnIndex) {
205 return columns[column].label + '\u2003'; 284 return columns[column].label + '\u2003';
206 } 285 }
207 return columns[column].label + (_sortDescending ? arrowUp : arrowDown); 286 return columns[column].label + (_sortDescending ? arrowUp : arrowDown);
208 } 287 }
209 288
210 dynamic getValue(int row, int column) { 289 dynamic getValue(int row, int column) {
211 return rows[row].values[column]; 290 return rows[row].values[column];
212 } 291 }
213 } 292 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/elements.html ('k') | runtime/observatory/lib/src/elements/class_tree.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698