OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 import 'dart:async'; |
| 6 |
| 7 import 'package:observatory/src/elements/helpers/rendering_queue.dart'; |
| 8 export 'package:observatory/src/elements/helpers/rendering_queue.dart'; |
| 9 |
| 10 /// A generic renderable object. |
| 11 abstract class Renderable { |
| 12 void render(); |
| 13 } |
| 14 |
| 15 /// Event related to a Renderable rendering phase. |
| 16 class RenderedEvent<T extends Renderable> { |
| 17 /// Renderable to which the event is related |
| 18 final T element; |
| 19 /// Is another rendering scheduled for this element. |
| 20 final bool otherRenderScheduled; |
| 21 |
| 22 RenderedEvent(this.element, this.otherRenderScheduled) { |
| 23 assert(element != null); |
| 24 assert(otherRenderScheduled != null); |
| 25 } |
| 26 } |
| 27 |
| 28 /// Scheduler for rendering operations. |
| 29 class RenderingScheduler<T extends Renderable> implements RenderingTask { |
| 30 bool _enabled = false; |
| 31 bool _dirty = false; |
| 32 bool _renderingScheduled = false; |
| 33 bool _notificationScheduled = false; |
| 34 /// Element managed by this scheduler. |
| 35 final T element; |
| 36 /// Queue used for rendering operations. |
| 37 final RenderingQueue queue; |
| 38 |
| 39 final StreamController<RenderedEvent<T>> _onRendered = |
| 40 new StreamController<RenderedEvent<T>>.broadcast(); |
| 41 Stream<RenderedEvent<T>> get onRendered => _onRendered.stream; |
| 42 |
| 43 /// Creates a new scheduler for an element. |
| 44 /// If no queue is provided it will create a new default configured queue. |
| 45 factory RenderingScheduler(T element, {RenderingQueue queue}) { |
| 46 assert(element != null); |
| 47 if (queue == null) { queue = new RenderingQueue(); } |
| 48 return new RenderingScheduler<T>._(element, queue); |
| 49 } |
| 50 |
| 51 RenderingScheduler._(this.element, this.queue); |
| 52 |
| 53 /// Enable the scheduler. |
| 54 /// New dirty or schedule request will be considered. |
| 55 void enable() { |
| 56 if (_enabled) return; |
| 57 _enabled = true; |
| 58 scheduleRendering(); |
| 59 } |
| 60 |
| 61 /// Disable the scheduler. |
| 62 /// New dirty or schedule request will be discarded. |
| 63 /// [optional] notify: send a final RenderEvent. |
| 64 void disable({bool notify: false}) { |
| 65 assert(notify != null); |
| 66 if (!_enabled) return; |
| 67 _enabled = false; |
| 68 if (notify) scheduleNotification(); |
| 69 } |
| 70 |
| 71 /// Set the object as dirty. A rendering will be scheduled. |
| 72 void dirty() { |
| 73 if (_dirty) return; |
| 74 _dirty = true; |
| 75 scheduleRendering(); |
| 76 } |
| 77 |
| 78 /// Schedules a new rendering phase. |
| 79 void scheduleRendering() { |
| 80 if (_renderingScheduled) return; |
| 81 if (!_enabled) return; |
| 82 queue.enqueue(this); |
| 83 _renderingScheduled = true; |
| 84 } |
| 85 |
| 86 /// Renders the element (if the scheduler is enabled). |
| 87 /// It will clear the dirty flag. |
| 88 void render() { |
| 89 if (!_enabled) return; |
| 90 _dirty = false; |
| 91 element.render(); |
| 92 _renderingScheduled = false; |
| 93 scheduleNotification(); |
| 94 if (_dirty) scheduleRendering(); |
| 95 } |
| 96 |
| 97 /// Schedules a notification. |
| 98 void scheduleNotification() { |
| 99 if (_notificationScheduled) return; |
| 100 _notify(); |
| 101 _notificationScheduled = true; |
| 102 } |
| 103 |
| 104 Future _notify() async { |
| 105 _onRendered.add(new RenderedEvent<T>(element, _dirty)); |
| 106 _notificationScheduled = false; |
| 107 } |
| 108 } |
OLD | NEW |