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..75e13dede1660060cd394519c7f0ebf84d736741 |
--- /dev/null |
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart |
@@ -0,0 +1,88 @@ |
+// 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:async'; |
+ |
+import 'package:observatory/src/elements/helpers/rendering_queue.dart'; |
+export 'package:observatory/src/elements/helpers/rendering_queue.dart'; |
+ |
+abstract class Renderable { |
+ void render(); |
+} |
+ |
+class RenderedEvent<T> { |
+ final T element; |
+ final bool otherRenderScheduled; |
+ RenderedEvent(this.element, this.otherRenderScheduled); |
+} |
+ |
+class RenderingScheduler<T extends Renderable> implements RenderingTask { |
+ bool _enabled = false; |
+ bool _dirty = false; |
+ bool _scheduledRendering = false; |
+ bool _scheduledNotification = false; |
+ final T element; |
+ final RenderingQueue queue; |
+ |
+ final StreamController<RenderedEvent<T>> _onRendered; |
+ final Stream<RenderedEvent<T>> onRendered; |
+ |
+ factory RenderingScheduler(T element, {RenderingQueue queue}) { |
+ assert(element != null); |
+ if (queue == null) { |
+ queue = new RenderingQueue(); |
+ } |
+ var controller = new StreamController<RenderedEvent<T>>(); |
+ var stream = controller.stream.asBroadcastStream(); |
+ return new RenderingScheduler<T>._(element, queue, controller, stream); |
+ } |
+ |
+ RenderingScheduler._(this.element, this.queue, this._onRendered, |
+ this.onRendered); |
+ |
+ void enable() { |
+ if (_enabled) return; |
+ _enabled = true; |
+ scheduleRendering(); |
+ } |
+ |
+ void disable({bool notify: false}) { |
+ if (!_enabled) return; |
+ _enabled = false; |
+ if (notify) scheduleNotification(); |
+ } |
+ |
+ void dirty() { |
+ if (_dirty) return; |
+ _dirty = true; |
+ scheduleRendering(); |
+ } |
+ |
+ void scheduleRendering() { |
+ if (_scheduledRendering) return; |
+ if (!_enabled) return; |
+ queue.enqueue(this); |
+ _scheduledRendering = true; |
+ } |
+ |
+ void render(){ |
+ if (!_enabled) return; |
+ _dirty = false; |
+ element.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; |
+ } |
+} |