OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library eval_box_element; | 5 library eval_box_element; |
6 | 6 |
7 import 'dart:html'; | 7 import 'dart:html'; |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'package:observatory/models.dart' as M; | 9 import 'package:observatory/models.dart' as M; |
10 import 'package:observatory/src/elements/helpers/any_ref.dart'; | 10 import 'package:observatory/src/elements/helpers/any_ref.dart'; |
11 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | 11 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
12 import 'package:observatory/src/elements/helpers/tag.dart'; | 12 import 'package:observatory/src/elements/helpers/tag.dart'; |
13 import 'package:observatory/src/elements/instance_ref.dart'; | 13 import 'package:observatory/src/elements/instance_ref.dart'; |
14 | 14 |
15 class EvalBoxElement extends HtmlElement implements Renderable { | 15 class EvalBoxElement extends HtmlElement implements Renderable { |
16 static const tag = const Tag<EvalBoxElement>('eval-box', | 16 static const tag = const Tag<EvalBoxElement>('eval-box', |
17 dependencies: const [ | 17 dependencies: const [InstanceRefElement.tag]); |
18 InstanceRefElement.tag | |
19 ]); | |
20 | 18 |
21 RenderingScheduler<EvalBoxElement> _r; | 19 RenderingScheduler<EvalBoxElement> _r; |
22 | 20 |
23 Stream<RenderedEvent<EvalBoxElement>> get onRendered => _r.onRendered; | 21 Stream<RenderedEvent<EvalBoxElement>> get onRendered => _r.onRendered; |
24 | 22 |
25 M.IsolateRef _isolate; | 23 M.IsolateRef _isolate; |
26 M.ObjectRef _context; | 24 M.ObjectRef _context; |
27 M.InstanceRepository _instances; | 25 M.InstanceRepository _instances; |
28 M.EvalRepository _eval; | 26 M.EvalRepository _eval; |
29 final _results = <_ExpressionDescription>[]; | 27 final _results = <_ExpressionDescription>[]; |
30 String _expression = ''; | 28 String _expression = ''; |
31 bool _multiline; | 29 bool _multiline; |
32 Iterable<String> _quickExpressions; | 30 Iterable<String> _quickExpressions; |
33 | 31 |
34 M.IsolateRef get isolate => _isolate; | 32 M.IsolateRef get isolate => _isolate; |
35 M.ObjectRef get context => _context; | 33 M.ObjectRef get context => _context; |
36 | 34 |
37 factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context, | 35 factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context, |
38 M.InstanceRepository instances, | 36 M.InstanceRepository instances, M.EvalRepository eval, |
39 M.EvalRepository eval, | 37 {bool multiline: false, |
40 {bool multiline: false, | 38 Iterable<String> quickExpressions: const [], |
41 Iterable<String> quickExpressions: const [], | 39 RenderingQueue queue}) { |
42 RenderingQueue queue}) { | |
43 assert(isolate != null); | 40 assert(isolate != null); |
44 assert(context != null); | 41 assert(context != null); |
45 assert(instances != null); | 42 assert(instances != null); |
46 assert(eval != null); | 43 assert(eval != null); |
47 assert(multiline != null); | 44 assert(multiline != null); |
48 assert(quickExpressions != null); | 45 assert(quickExpressions != null); |
49 EvalBoxElement e = document.createElement(tag.name); | 46 EvalBoxElement e = document.createElement(tag.name); |
50 e._r = new RenderingScheduler(e, queue: queue); | 47 e._r = new RenderingScheduler(e, queue: queue); |
51 e._isolate = isolate; | 48 e._isolate = isolate; |
52 e._context = context; | 49 e._context = context; |
(...skipping 15 matching lines...) Expand all Loading... |
68 @override | 65 @override |
69 void detached() { | 66 void detached() { |
70 super.detached(); | 67 super.detached(); |
71 _r.disable(notify: true); | 68 _r.disable(notify: true); |
72 children = []; | 69 children = []; |
73 _results.clear(); | 70 _results.clear(); |
74 } | 71 } |
75 | 72 |
76 void render() { | 73 void render() { |
77 children = [ | 74 children = [ |
78 new DivElement()..classes = ['quicks'] | 75 new DivElement() |
79 ..children = _quickExpressions.map((q) => | 76 ..classes = ['quicks'] |
80 new ButtonElement() | 77 ..children = _quickExpressions.map((q) => new ButtonElement() |
81 ..text = q | 78 ..text = q |
82 ..onClick.listen((_) { | 79 ..onClick.listen((_) { |
83 _expression = q; | 80 _expression = q; |
84 _run(); | 81 _run(); |
85 }) | 82 })), |
86 ), | 83 new DivElement() |
87 new DivElement()..classes = ['heading'] | 84 ..classes = ['heading'] |
88 ..children = [ | 85 ..children = [ |
89 new FormElement() | 86 new FormElement() |
90 ..autocomplete = 'on' | 87 ..autocomplete = 'on' |
91 ..children = [ | 88 ..children = [ |
92 _multiline ? _createEvalTextArea() : _createEvalTextBox(), | 89 _multiline ? _createEvalTextArea() : _createEvalTextBox(), |
93 new SpanElement()..classes = ['buttons'] | 90 new SpanElement() |
| 91 ..classes = ['buttons'] |
94 ..children = [ | 92 ..children = [ |
95 _createEvalButton(), | 93 _createEvalButton(), |
96 _createMultilineCheckbox(), | 94 _createMultilineCheckbox(), |
97 new SpanElement()..text = 'multi-line' | 95 new SpanElement()..text = 'multi-line' |
98 ] | 96 ] |
99 ] | 97 ] |
100 ], | 98 ], |
101 new TableElement() | 99 new TableElement() |
102 ..children = _results.reversed.map((result) => | 100 ..children = _results.reversed |
103 new TableRowElement() | 101 .map((result) => new TableRowElement() |
104 ..children = [ | 102 ..children = [ |
105 new TableCellElement()..classes = ['historyExpr'] | 103 new TableCellElement() |
106 ..children = [ | 104 ..classes = ['historyExpr'] |
107 new ButtonElement()..text = result.expression | 105 ..children = [ |
108 ..onClick.listen((_) { | 106 new ButtonElement() |
109 _expression = result.expression; | 107 ..text = result.expression |
110 _r.dirty(); | 108 ..onClick.listen((_) { |
111 }) | 109 _expression = result.expression; |
112 ], | 110 _r.dirty(); |
113 new TableCellElement()..classes = ['historyValue'] | 111 }) |
114 ..children = [ | 112 ], |
115 result.isPending | 113 new TableCellElement() |
116 ? (new SpanElement()..text = 'Pending...') | 114 ..classes = ['historyValue'] |
117 : anyRef(_isolate, result.value, _instances, | 115 ..children = [ |
118 queue: _r.queue) | 116 result.isPending |
119 ], | 117 ? (new SpanElement()..text = 'Pending...') |
120 new TableCellElement()..classes = ['historyDelete'] | 118 : anyRef(_isolate, result.value, _instances, |
121 ..children = [ | 119 queue: _r.queue) |
122 new ButtonElement()..text = '✖ Remove' | 120 ], |
123 ..onClick.listen((_) { | 121 new TableCellElement() |
124 _results.remove(result); | 122 ..classes = ['historyDelete'] |
125 _r.dirty(); | 123 ..children = [ |
126 }) | 124 new ButtonElement() |
127 ] | 125 ..text = '✖ Remove' |
128 ]).toList() | 126 ..onClick.listen((_) { |
| 127 _results.remove(result); |
| 128 _r.dirty(); |
| 129 }) |
| 130 ] |
| 131 ]) |
| 132 .toList() |
129 ]; | 133 ]; |
130 } | 134 } |
131 | 135 |
132 TextInputElement _createEvalTextArea() { | 136 TextInputElement _createEvalTextArea() { |
133 var area = new TextAreaElement() | 137 var area = new TextAreaElement() |
134 ..classes = ['textbox'] | 138 ..classes = ['textbox'] |
135 ..placeholder = 'evaluate an expression' | 139 ..placeholder = 'evaluate an expression' |
136 ..value = _expression | 140 ..value = _expression |
137 ..onKeyUp | 141 ..onKeyUp.where((e) => e.key == '\n').listen((e) { |
138 .where((e) => e.key == '\n') | 142 e.preventDefault(); |
139 .listen((e) { | 143 _run(); |
140 e.preventDefault(); | 144 }); |
141 _run(); | |
142 }); | |
143 area.onInput.listen((e) { | 145 area.onInput.listen((e) { |
144 _expression = area.value; | 146 _expression = area.value; |
145 }); | 147 }); |
146 return area; | 148 return area; |
147 } | 149 } |
148 | 150 |
149 TextInputElement _createEvalTextBox() { | 151 TextInputElement _createEvalTextBox() { |
150 _expression = (_expression ?? '').split('\n')[0]; | 152 _expression = (_expression ?? '').split('\n')[0]; |
151 var textbox = new TextInputElement() | 153 var textbox = new TextInputElement() |
152 ..classes = ['textbox'] | 154 ..classes = ['textbox'] |
153 ..placeholder = 'evaluate an expression' | 155 ..placeholder = 'evaluate an expression' |
154 ..value = _expression | 156 ..value = _expression |
155 ..onKeyUp | 157 ..onKeyUp.where((e) => e.key == '\n').listen((e) { |
156 .where((e) => e.key == '\n') | 158 e.preventDefault(); |
157 .listen((e) { | 159 _run(); |
158 e.preventDefault(); | 160 }); |
159 _run(); | |
160 }); | |
161 textbox.onInput.listen((e) { | 161 textbox.onInput.listen((e) { |
162 _expression = textbox.value; | 162 _expression = textbox.value; |
163 }); | 163 }); |
164 return textbox; | 164 return textbox; |
165 } | 165 } |
166 | 166 |
167 ButtonElement _createEvalButton() { | 167 ButtonElement _createEvalButton() { |
168 final button = new ButtonElement() | 168 final button = new ButtonElement() |
169 ..text = 'evaluate' | 169 ..text = 'evaluate' |
170 ..onClick.listen((e) { | 170 ..onClick.listen((e) { |
171 e.preventDefault(); | 171 e.preventDefault(); |
172 _run(); | 172 _run(); |
173 }); | 173 }); |
174 return button; | 174 return button; |
175 } | 175 } |
176 | 176 |
177 CheckboxInputElement _createMultilineCheckbox() { | 177 CheckboxInputElement _createMultilineCheckbox() { |
178 final checkbox = new CheckboxInputElement() | 178 final checkbox = new CheckboxInputElement()..checked = _multiline; |
179 ..checked = _multiline; | |
180 checkbox.onClick.listen((e) { | 179 checkbox.onClick.listen((e) { |
181 e.preventDefault(); | 180 e.preventDefault(); |
182 _multiline = checkbox.checked; | 181 _multiline = checkbox.checked; |
183 _r.dirty(); | 182 _r.dirty(); |
184 }); | 183 }); |
185 return checkbox; | 184 return checkbox; |
186 } | 185 } |
187 | 186 |
188 Future _run() async { | 187 Future _run() async { |
189 if (_expression == null || _expression.isEmpty) return; | 188 if (_expression == null || _expression.isEmpty) return; |
190 final expression = _expression; | 189 final expression = _expression; |
191 _expression = null; | 190 _expression = null; |
192 final result = new _ExpressionDescription.pending(expression); | 191 final result = new _ExpressionDescription.pending(expression); |
193 _results.add(result); | 192 _results.add(result); |
194 _r.dirty(); | 193 _r.dirty(); |
195 final index = _results.indexOf(result); | 194 final index = _results.indexOf(result); |
196 _results[index] = new _ExpressionDescription(expression, | 195 _results[index] = new _ExpressionDescription( |
197 await _eval.evaluate(_isolate, _context, expression)); | 196 expression, await _eval.evaluate(_isolate, _context, expression)); |
198 _r.dirty(); | 197 _r.dirty(); |
199 } | 198 } |
200 } | 199 } |
201 | 200 |
202 class _ExpressionDescription { | 201 class _ExpressionDescription { |
203 final String expression; | 202 final String expression; |
204 final M.ObjectRef value; | 203 final M.ObjectRef value; |
205 bool get isPending => value == null; | 204 bool get isPending => value == null; |
206 | 205 |
207 _ExpressionDescription(this.expression, this.value); | 206 _ExpressionDescription(this.expression, this.value); |
208 _ExpressionDescription.pending(this.expression) | 207 _ExpressionDescription.pending(this.expression) : value = null; |
209 : value = null; | |
210 } | 208 } |
OLD | NEW |