blob: 771ddf9ed5542e0388a3c8c812a1ce9e8f8e75ba [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library eval_box_element;
import 'dart:html';
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/instance_ref.dart';
class EvalBoxElement extends CustomElement implements Renderable {
RenderingScheduler<EvalBoxElement> _r;
Stream<RenderedEvent<EvalBoxElement>> get onRendered => _r.onRendered;
M.IsolateRef _isolate;
M.ObjectRef _context;
M.ObjectRepository _objects;
M.EvalRepository _eval;
final _results = <_ExpressionDescription>[];
String _expression = '';
bool _multiline;
Iterable<String> _quickExpressions;
M.IsolateRef get isolate => _isolate;
M.ObjectRef get context => _context;
factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context,
M.ObjectRepository objects, M.EvalRepository eval,
{bool multiline: false,
Iterable<String> quickExpressions: const [],
RenderingQueue queue}) {
assert(isolate != null);
assert(context != null);
assert(objects != null);
assert(eval != null);
assert(multiline != null);
assert(quickExpressions != null);
EvalBoxElement e = new EvalBoxElement.created();
e._r = new RenderingScheduler<EvalBoxElement>(e, queue: queue);
e._isolate = isolate;
e._context = context;
e._objects = objects;
e._eval = eval;
e._multiline = multiline;
e._quickExpressions = new List.unmodifiable(quickExpressions);
return e;
}
EvalBoxElement.created() : super.created('eval-box');
@override
void attached() {
super.attached();
_r.enable();
}
@override
void detached() {
super.detached();
_r.disable(notify: true);
children = <Element>[];
_results.clear();
}
void render() {
children = <Element>[
new DivElement()
..classes = ['quicks']
..children = _quickExpressions
.map<Element>((q) => new ButtonElement()
..text = q
..onClick.listen((_) {
_expression = q;
_run();
}))
.toList(),
new DivElement()
..classes = ['heading']
..children = <Element>[
new FormElement()
..autocomplete = 'on'
..children = <Element>[
_multiline ? _createEvalTextArea() : _createEvalTextBox(),
new SpanElement()
..classes = ['buttons']
..children = <Element>[
_createEvalButton(),
_createMultilineCheckbox(),
new SpanElement()..text = 'Multi-line'
]
]
],
new TableElement()
..children = _results.reversed
.map<Element>((result) => new TableRowElement()
..children = <Element>[
new TableCellElement()
..classes = ['historyExpr']
..children = <Element>[
new ButtonElement()
..text = result.expression
..onClick.listen((_) {
_expression = result.expression;
_r.dirty();
})
],
new TableCellElement()
..classes = ['historyValue']
..children = <Element>[
result.isPending
? (new SpanElement()..text = 'Pending...')
: anyRef(_isolate, result.value, _objects,
queue: _r.queue)
],
new TableCellElement()
..classes = ['historyDelete']
..children = <Element>[
new ButtonElement()
..text = '✖ Remove'
..onClick.listen((_) {
_results.remove(result);
_r.dirty();
})
]
])
.toList()
];
}
TextAreaElement _createEvalTextArea() {
var area = new TextAreaElement()
..classes = ['textbox']
..placeholder = 'evaluate an expression'
..value = _expression
..onKeyUp.where((e) => e.key == '\n').listen((e) {
e.preventDefault();
_run();
});
area.onInput.listen((e) {
_expression = area.value;
});
return area;
}
TextInputElement _createEvalTextBox() {
_expression = (_expression ?? '').split('\n')[0];
var textbox = new TextInputElement()
..classes = ['textbox']
..placeholder = 'evaluate an expression'
..value = _expression
..onKeyUp.where((e) => e.key == '\n').listen((e) {
e.preventDefault();
_run();
});
textbox.onInput.listen((e) {
_expression = textbox.value;
});
return textbox;
}
ButtonElement _createEvalButton() {
final button = new ButtonElement()
..text = 'Evaluate'
..onClick.listen((e) {
e.preventDefault();
_run();
});
return button;
}
CheckboxInputElement _createMultilineCheckbox() {
final checkbox = new CheckboxInputElement()..checked = _multiline;
checkbox.onClick.listen((e) {
e.preventDefault();
_multiline = checkbox.checked;
_r.dirty();
});
return checkbox;
}
Future _run() async {
if (_expression == null || _expression.isEmpty) return;
final expression = _expression;
_expression = null;
final result = new _ExpressionDescription.pending(expression);
_results.add(result);
_r.dirty();
final index = _results.indexOf(result);
_results[index] = new _ExpressionDescription(
expression, await _eval.evaluate(_isolate, _context, expression));
_r.dirty();
}
}
class _ExpressionDescription {
final String expression;
final M.ObjectRef value;
bool get isPending => value == null;
_ExpressionDescription(this.expression, this.value);
_ExpressionDescription.pending(this.expression) : value = null;
}