Chromium Code Reviews| 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; |
| + } |
| +} |