Index: runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart |
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2cfbcf0ba78cf12b89d49f99a7b65c7f426c970c |
--- /dev/null |
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart |
@@ -0,0 +1,79 @@ |
+// Copyright (c) 2016, 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. |
+ |
+import 'dart:html'; |
+import 'dart:async'; |
+ |
+abstract class Renderable { |
+ render(); |
+} |
+ |
+typedef void RenderingCallback(); |
+ |
+abstract class AsyncRenderable extends Renderable { |
+ Future<RenderingCallback> render(); |
+} |
+ |
+class RenderedEvent<T> { |
+ final T element; |
+ final bool otherRenderScheduled; |
+ RenderedEvent(this.element, this.otherRenderScheduled); |
+} |
+ |
+class RenderingScheduler<T extends Renderable> { |
+ bool _dirty = false; |
+ bool _scheduledRendering = false; |
+ bool _scheduledNotification = false; |
+ final T element; |
+ |
+ final StreamController<RenderedEvent<T>> _onRendered; |
+ final Stream<RenderedEvent<T>> onRendered; |
+ |
+ factory RenderingScheduler(T element) { |
+ assert(element != null); |
+ var controller = new StreamController<RenderedEvent<T>>(); |
+ var stream = controller.stream.asBroadcastStream(); |
+ return new RenderingScheduler<T>._(element, controller, stream); |
+ } |
+ |
+ RenderingScheduler._(this.element, this._onRendered, this.onRendered); |
+ |
+ void dirty() { |
+ if (_dirty) return; |
+ _dirty = true; |
+ scheduleRendering(); |
+ } |
+ |
+ void scheduleRendering() { |
+ if (_scheduledRendering) return; |
+ _render(); |
+ _scheduledRendering = true; |
+ } |
+ |
+ Future _render() async { |
+ _dirty = false; |
+ RenderingCallback render; |
+ if (element is AsyncRenderable) { |
+ render = await element.render(); |
Cutch
2016/07/12 16:24:36
just have one animationframe callback and render a
|
+ } else { |
+ render = element.render; |
+ } |
+ await window.animationFrame; |
+ render(); |
+ _scheduledRendering = false; |
+ scheduleNotification(); |
+ if (_dirty) scheduleRendering(); |
+ } |
+ |
+ void scheduleNotification() { |
+ if (_scheduledNotification) return; |
+ _notify(); |
+ _scheduledNotification = true; |
+ } |
+ |
+ Future _notify() async { |
+ _onRendered.add(new RenderedEvent<T>(element, _dirty)); |
+ _scheduledNotification = false; |
+ } |
+} |