From 92857ceef8a2b74cb1cedc00b1122d4891fc70e5 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 30 Aug 2015 12:17:18 -0700 Subject: [PATCH] Add dartdoc for base --- sky/packages/sky/lib/base/debug.dart | 14 +++ sky/packages/sky/lib/base/hit_test.dart | 34 ++++++- sky/packages/sky/lib/base/image_resource.dart | 14 +++ sky/packages/sky/lib/base/lerp.dart | 11 +++ sky/packages/sky/lib/base/node.dart | 56 +++++++++--- sky/packages/sky/lib/base/pointer_router.dart | 29 ++++-- sky/packages/sky/lib/base/scheduler.dart | 42 +++++++-- sky/packages/sky/lib/rendering.dart | 32 +++---- sky/packages/sky/lib/widgets.dart | 88 +++++++++---------- 9 files changed, 229 insertions(+), 91 deletions(-) diff --git a/sky/packages/sky/lib/base/debug.dart b/sky/packages/sky/lib/base/debug.dart index f025e9959e8..ae396dfd492 100644 --- a/sky/packages/sky/lib/base/debug.dart +++ b/sky/packages/sky/lib/base/debug.dart @@ -4,6 +4,7 @@ import 'dart:sky' as sky; +/// Indicates whether we're running with asserts enabled. final bool inDebugBuild = _initInDebugBuild(); bool _initInDebugBuild() { @@ -16,16 +17,29 @@ bool _initInDebugBuild() { return _inDebug; } +/// Causes each RenderBox to paint a box around its bounds. bool debugPaintSizeEnabled = false; + +/// The color to use when painting RenderObject bounds. const sky.Color debugPaintSizeColor = const sky.Color(0xFF00FFFF); +/// Causes each RenderBox to paint a line at each of its baselines. bool debugPaintBaselinesEnabled = false; + +/// The color to use when painting alphabetic baselines. const sky.Color debugPaintAlphabeticBaselineColor = const sky.Color(0xFF00FF00); + +/// The color ot use when painting ideographic baselines. const sky.Color debugPaintIdeographicBaselineColor = const sky.Color(0xFFFFD000); +/// Causes each Layer to paint a box around its bounds. bool debugPaintLayerBordersEnabled = false; + +/// The color to use when painting Layer borders. const sky.Color debugPaintLayerBordersColor = const sky.Color(0xFFFF9800); +/// Causes RenderObjects to paint warnings when painting outside their bounds. bool debugPaintBoundsEnabled = false; +/// Slows down animations by this factor to help in development. double timeDilation = 1.0; diff --git a/sky/packages/sky/lib/base/hit_test.dart b/sky/packages/sky/lib/base/hit_test.dart index 64a17158b10..c022c013ace 100644 --- a/sky/packages/sky/lib/base/hit_test.dart +++ b/sky/packages/sky/lib/base/hit_test.dart @@ -4,12 +4,22 @@ import 'dart:sky' as sky; +/// The outcome of running an event handler. enum EventDisposition { + /// The event handler ignored this event. ignored, + + /// The event handler did not ignore the event but other event handlers should + /// process the event as well. processed, + + /// The event handler did not ignore the event and other event handlers + /// should not process the event. consumed, } +/// Merges two [EventDisposition] values such that the result indicates the +/// maximum amount of processing indicated by the two inputs. EventDisposition combineEventDispositions(EventDisposition left, EventDisposition right) { if (left == EventDisposition.consumed || right == EventDisposition.consumed) return EventDisposition.consumed; @@ -18,22 +28,42 @@ EventDisposition combineEventDispositions(EventDisposition left, EventDispositio return EventDisposition.ignored; } +/// An object that can handle events. abstract class HitTestTarget { + /// Override this function to receive events. EventDisposition handleEvent(sky.Event event, HitTestEntry entry); } +/// Data collected during a hit test about a specific [HitTestTarget]. +/// +/// Subclass this object to pass additional information from the hit test phase +/// to the event propagation phase. class HitTestEntry { const HitTestEntry(this.target); + + /// The [HitTestTarget] encountered during the hit test. final HitTestTarget target; } +/// The result of performing a hit test. class HitTestResult { HitTestResult({ List path }) : path = path != null ? path : new List(); + /// The list of [HitTestEntry] objects recorded during the hit test. + /// + /// The first entry in the path is the least specific, typically the one at + /// the root of tree being hit tested. Event propagation starts with the most + /// specific (i.e., last) entry and proceeds in reverse order through the + /// path. final List path; - void add(HitTestEntry data) { - path.add(data); + /// Add a [HitTestEntry] to the path. + /// + /// The new entry is added at the end of the path, which means entries should + /// be added in order from last specific to most specific, typically during a + /// downward walk in the tree being hit tested. + void add(HitTestEntry entry) { + path.add(entry); } } diff --git a/sky/packages/sky/lib/base/image_resource.dart b/sky/packages/sky/lib/base/image_resource.dart index 58800c993e2..d8e6fc50ce7 100644 --- a/sky/packages/sky/lib/base/image_resource.dart +++ b/sky/packages/sky/lib/base/image_resource.dart @@ -5,8 +5,14 @@ import 'dart:async'; import 'dart:sky' as sky; +/// A callback for when the image is available. typedef void ImageListener(sky.Image image); +/// A handle to an image resource +/// +/// ImageResource represents a handle to a [sky.Image] object. The underlying +/// image object might change over time, either because the image is animating +/// or because the underlying image resource was mutated. class ImageResource { ImageResource(this._futureImage) { _futureImage.then(_handleImageLoaded, onError: _handleImageError); @@ -17,14 +23,22 @@ class ImageResource { sky.Image _image; final List _listeners = new List(); + /// The first concrete [sky.Image] object represented by this handle. + /// + /// Instead of receivingly only the first image, most clients will want to + /// [addListener] to be notified whenever a a concrete image is available. Future get first => _futureImage; + /// Adds a listener callback that is called whenever a concrete [sky.Image] + /// object is available. Note: If a concrete image is available currently, + /// this object will call the listener synchronously. void addListener(ImageListener listener) { _listeners.add(listener); if (_resolved) listener(_image); } + /// Stop listening for new concrete [sky.Image] objects. void removeListener(ImageListener listener) { _listeners.remove(listener); } diff --git a/sky/packages/sky/lib/base/lerp.dart b/sky/packages/sky/lib/base/lerp.dart index da5c144e946..33c25a45de5 100644 --- a/sky/packages/sky/lib/base/lerp.dart +++ b/sky/packages/sky/lib/base/lerp.dart @@ -4,6 +4,7 @@ import 'dart:sky'; +/// Linearly interpolate between two numbers. num lerpNum(num a, num b, double t) { if (a == null && b == null) return null; @@ -18,6 +19,10 @@ Color _scaleAlpha(Color a, double factor) { return a.withAlpha((a.alpha * factor).round()); } +/// Linearly interpolate between two [Color] objects. +/// +/// If either color is null, this function linearly interpolates from a +/// transparent instance of othe other color. Color lerpColor(Color a, Color b, double t) { if (a == null && b == null) return null; @@ -33,6 +38,9 @@ Color lerpColor(Color a, Color b, double t) { ); } +/// Linearly interpolate between two [Offset] objects. +/// +/// If either offset is null, this function interpolates from [Offset.zero]. Offset lerpOffset(Offset a, Offset b, double t) { if (a == null && b == null) return null; @@ -43,6 +51,9 @@ Offset lerpOffset(Offset a, Offset b, double t) { return new Offset(lerpNum(a.dx, b.dx, t), lerpNum(a.dy, b.dy, t)); } +/// Linearly interpolate between two [Rect] objects. +/// +/// If either rect is null, this function interpolates from 0x0x0x0. Rect lerpRect(Rect a, Rect b, double t) { if (a == null && b == null) return null; diff --git a/sky/packages/sky/lib/base/node.dart b/sky/packages/sky/lib/base/node.dart index 43acf8adec9..7d5f285499a 100644 --- a/sky/packages/sky/lib/base/node.dart +++ b/sky/packages/sky/lib/base/node.dart @@ -2,45 +2,73 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/// An abstract node in a tree +/// +/// AbstractNode has as notion of depth, attachment, and parent, but does not +/// have a model for children. class AbstractNode { // AbstractNode represents a node in a tree. // The AbstractNode protocol is described in README.md. int _depth = 0; + /// The depth of this node in the tree. + /// + /// The depth of nodes in a tree monotonically increases as you traverse down + /// the trees. int get depth => _depth; - void redepthChild(AbstractNode child) { // internal, do not call + + /// Call only from overrides of [redepthChildren] + void redepthChild(AbstractNode child) { assert(child._attached == _attached); if (child._depth <= _depth) { child._depth = _depth + 1; child.redepthChildren(); } } - void redepthChildren() { // internal, do not call - // override this in subclasses with child nodes - // simply call redepthChild(child) for each child - } + + /// Override this function in subclasses with child nodes to call + /// redepthChild(child) for each child. Do not call directly. + void redepthChildren() { } bool _attached = false; + /// Whether this node is in a tree whose root is attached to something. bool get attached => _attached; + + /// Mark this node as attached. + /// + /// Typically called only from overrides of [attachChildren] and to mark the + /// root of a tree attached. void attach() { - // override this in subclasses with child nodes - // simply call attach() for each child then call your superclass _attached = true; attachChildren(); } - attachChildren() { } // workaround for lack of inter-class mixins in Dart + + /// Override this function in subclasses with child to call attach() for each + /// child. Do not call directly. + attachChildren() { } + + /// Mark this node as detached. + /// + /// Typically called only from overrides for [detachChildren] and to mark the + /// root of a tree detached. void detach() { - // override this in subclasses with child nodes - // simply call detach() for each child then call your superclass _attached = false; detachChildren(); } - detachChildren() { } // workaround for lack of inter-class mixins in Dart + + /// Override this function in subclasses with child to call detach() for each + /// child. Do not call directly. + detachChildren() { } + + // TODO(ianh): remove attachChildren()/detachChildren() workaround once mixins can use super. AbstractNode _parent; + /// The parent of this node in the tree. AbstractNode get parent => _parent; - void adoptChild(AbstractNode child) { // only for use by subclasses + + /// Subclasses should call this function when they acquire a new child. + void adoptChild(AbstractNode child) { assert(child != null); assert(child._parent == null); child._parent = this; @@ -48,7 +76,9 @@ class AbstractNode { child.attach(); redepthChild(child); } - void dropChild(AbstractNode child) { // only for use by subclasses + + /// Subclasses should call this function when they lose a child. + void dropChild(AbstractNode child) { assert(child != null); assert(child._parent == this); assert(child.attached == attached); diff --git a/sky/packages/sky/lib/base/pointer_router.dart b/sky/packages/sky/lib/base/pointer_router.dart index 14d94f7cdc2..5de518b1e40 100644 --- a/sky/packages/sky/lib/base/pointer_router.dart +++ b/sky/packages/sky/lib/base/pointer_router.dart @@ -4,31 +4,44 @@ import 'dart:sky' as sky; -typedef void _Route(sky.PointerEvent event); +/// A callback that receives a [sky.PointerEvent] +typedef void PointerRoute(sky.PointerEvent event); +/// A routing table for [sky.PointerEvent] events. class PointerRouter { - final Map> _routeMap = new Map>(); + final Map> _routeMap = new Map>(); - void addRoute(int pointer, _Route route) { - List<_Route> routes = _routeMap.putIfAbsent(pointer, () => new List<_Route>()); + /// Adds a route to the routing table + /// + /// Whenever this object routes a [sky.PointerEvent] corresponding to + /// pointer, call route. + void addRoute(int pointer, PointerRoute route) { + List routes = _routeMap.putIfAbsent(pointer, () => new List()); assert(!routes.contains(route)); routes.add(route); } - void removeRoute(int pointer, _Route route) { + /// Removes a route from the routing table + /// + /// No longer call route when routing a [sky.PointerEvent] corresponding to + /// pointer. Requires that this route was previously added to the router. + void removeRoute(int pointer, PointerRoute route) { assert(_routeMap.containsKey(pointer)); - List<_Route> routes = _routeMap[pointer]; + List routes = _routeMap[pointer]; assert(routes.contains(route)); routes.remove(route); if (routes.isEmpty) _routeMap.remove(pointer); } + /// Call the routes registed for this pointer event. + /// + /// Calls the routes in the order in which they were added to the route. void route(sky.PointerEvent event) { - List<_Route> routes = _routeMap[event.pointer]; + List routes = _routeMap[event.pointer]; if (routes == null) return; - for (_Route route in new List<_Route>.from(routes)) + for (PointerRoute route in new List.from(routes)) route(event); } } diff --git a/sky/packages/sky/lib/base/scheduler.dart b/sky/packages/sky/lib/base/scheduler.dart index 81a2fbbf331..c0e0ecea8a8 100644 --- a/sky/packages/sky/lib/base/scheduler.dart +++ b/sky/packages/sky/lib/base/scheduler.dart @@ -7,22 +7,33 @@ import 'dart:sky' as sky; import 'package:sky/base/debug.dart'; -typedef void Callback(double timeStamp); +/// A callback from the scheduler +/// +/// The timeStamp is the number of milliseconds since the beginning of the +/// scheduler's epoch. Use timeStamp to determine how far to advance animation +/// timelines so that all the animations in the system are synchronized to a +/// common time base. +typedef void SchedulerCallback(double timeStamp); bool _haveScheduledVisualUpdate = false; int _nextCallbackId = 1; -final List _persistentCallbacks = new List(); -Map _transientCallbacks = new LinkedHashMap(); +final List _persistentCallbacks = new List(); +Map _transientCallbacks = new LinkedHashMap(); final Set _removedIds = new Set(); +/// Called by the engine to produce a new frame. +/// +/// This function first calls all the callbacks registered by +/// [requestAnimationFrame] and then calls all the callbacks registered by +/// [addPersistentFrameCallback], which typically drive the rendering pipeline. void beginFrame(double timeStamp) { timeStamp /= timeDilation; _haveScheduledVisualUpdate = false; - Map callbacks = _transientCallbacks; - _transientCallbacks = new Map(); + Map callbacks = _transientCallbacks; + _transientCallbacks = new Map(); callbacks.forEach((id, callback) { if (!_removedIds.contains(id)) @@ -30,30 +41,45 @@ void beginFrame(double timeStamp) { }); _removedIds.clear(); - for (Callback callback in _persistentCallbacks) + for (SchedulerCallback callback in _persistentCallbacks) callback(timeStamp); } +/// Registers [beginFrame] callback with the engine. void init() { sky.view.setFrameCallback(beginFrame); } -void addPersistentFrameCallback(Callback callback) { +/// Call callback every frame. +void addPersistentFrameCallback(SchedulerCallback callback) { _persistentCallbacks.add(callback); } -int requestAnimationFrame(Callback callback) { +/// Schedule a callback for the next frame. +/// +/// The callback will be run prior to flushing the main rendering pipeline. +/// Typically, requestAnimationFrame is used to throttle writes into the +/// rendering pipeline until the system is ready to accept a new frame. For +/// example, if you wanted to tick through an animation, you should use +/// requestAnimation frame to determine when to tick the animation. The callback +/// is passed a timeStamp that you can use to determine how far along the +/// timeline to advance your animation. +/// +/// Returns an id that can be used to unschedule this callback. +int requestAnimationFrame(SchedulerCallback callback) { int id = _nextCallbackId++; _transientCallbacks[id] = callback; ensureVisualUpdate(); return id; } +/// Cancel the callback identified by id. void cancelAnimationFrame(int id) { _transientCallbacks.remove(id); _removedIds.add(id); } +/// Ensure that a frame will be produced after this function is called. void ensureVisualUpdate() { if (_haveScheduledVisualUpdate) return; diff --git a/sky/packages/sky/lib/rendering.dart b/sky/packages/sky/lib/rendering.dart index f2ac4f58530..23686e85c2a 100644 --- a/sky/packages/sky/lib/rendering.dart +++ b/sky/packages/sky/lib/rendering.dart @@ -4,21 +4,21 @@ /// Includes and re-exports all Sky rendering classes. -export 'rendering/auto_layout.dart'; -export 'rendering/block.dart'; -export 'rendering/box.dart'; -export 'rendering/flex.dart'; -export 'rendering/grid.dart'; -export 'rendering/image.dart'; -export 'rendering/layer.dart'; -export 'rendering/object.dart'; -export 'rendering/paragraph.dart'; -export 'rendering/proxy_box.dart'; -export 'rendering/shifted_box.dart'; -export 'rendering/sky_binding.dart'; -export 'rendering/stack.dart'; -export 'rendering/toggleable.dart'; -export 'rendering/view.dart'; -export 'rendering/viewport.dart'; +export 'package:sky/rendering/auto_layout.dart'; +export 'package:sky/rendering/block.dart'; +export 'package:sky/rendering/box.dart'; +export 'package:sky/rendering/flex.dart'; +export 'package:sky/rendering/grid.dart'; +export 'package:sky/rendering/image.dart'; +export 'package:sky/rendering/layer.dart'; +export 'package:sky/rendering/object.dart'; +export 'package:sky/rendering/paragraph.dart'; +export 'package:sky/rendering/proxy_box.dart'; +export 'package:sky/rendering/shifted_box.dart'; +export 'package:sky/rendering/sky_binding.dart'; +export 'package:sky/rendering/stack.dart'; +export 'package:sky/rendering/toggleable.dart'; +export 'package:sky/rendering/view.dart'; +export 'package:sky/rendering/viewport.dart'; export 'package:vector_math/vector_math.dart' show Matrix4; diff --git a/sky/packages/sky/lib/widgets.dart b/sky/packages/sky/lib/widgets.dart index cf205b09934..5f3d2d9a152 100644 --- a/sky/packages/sky/lib/widgets.dart +++ b/sky/packages/sky/lib/widgets.dart @@ -4,49 +4,49 @@ /// Includes and re-exports all Sky widgets classes. -export 'widgets/animated_component.dart'; -export 'widgets/animated_container.dart'; -export 'widgets/basic.dart'; -export 'widgets/button_base.dart'; -export 'widgets/card.dart'; -export 'widgets/checkbox.dart'; -export 'widgets/date_picker.dart'; -export 'widgets/default_text_style.dart'; -export 'widgets/dialog.dart'; -export 'widgets/dismissable.dart'; -export 'widgets/drag_target.dart'; -export 'widgets/drawer.dart'; -export 'widgets/drawer_divider.dart'; -export 'widgets/drawer_header.dart'; -export 'widgets/drawer_item.dart'; -export 'widgets/flat_button.dart'; -export 'widgets/floating_action_button.dart'; -export 'widgets/focus.dart'; -export 'widgets/framework.dart'; -export 'widgets/gesture_detector.dart'; -export 'widgets/icon.dart'; -export 'widgets/icon_button.dart'; -export 'widgets/ink_well.dart'; -export 'widgets/material.dart'; -export 'widgets/material_button.dart'; -export 'widgets/mimic.dart'; -export 'widgets/mimic_overlay.dart'; -export 'widgets/mixed_viewport.dart'; -export 'widgets/modal_overlay.dart'; -export 'widgets/navigator.dart'; -export 'widgets/popup_menu.dart'; -export 'widgets/popup_menu_item.dart'; -export 'widgets/progress_indicator.dart'; -export 'widgets/radio.dart'; -export 'widgets/raised_button.dart'; -export 'widgets/scaffold.dart'; -export 'widgets/scrollable.dart'; -export 'widgets/snack_bar.dart'; -export 'widgets/switch.dart'; -export 'widgets/tabs.dart'; -export 'widgets/theme.dart'; -export 'widgets/title.dart'; -export 'widgets/tool_bar.dart'; -export 'widgets/transitions.dart'; +export 'package:sky/widgets/animated_component.dart'; +export 'package:sky/widgets/animated_container.dart'; +export 'package:sky/widgets/basic.dart'; +export 'package:sky/widgets/button_base.dart'; +export 'package:sky/widgets/card.dart'; +export 'package:sky/widgets/checkbox.dart'; +export 'package:sky/widgets/date_picker.dart'; +export 'package:sky/widgets/default_text_style.dart'; +export 'package:sky/widgets/dialog.dart'; +export 'package:sky/widgets/dismissable.dart'; +export 'package:sky/widgets/drag_target.dart'; +export 'package:sky/widgets/drawer.dart'; +export 'package:sky/widgets/drawer_divider.dart'; +export 'package:sky/widgets/drawer_header.dart'; +export 'package:sky/widgets/drawer_item.dart'; +export 'package:sky/widgets/flat_button.dart'; +export 'package:sky/widgets/floating_action_button.dart'; +export 'package:sky/widgets/focus.dart'; +export 'package:sky/widgets/framework.dart'; +export 'package:sky/widgets/gesture_detector.dart'; +export 'package:sky/widgets/icon.dart'; +export 'package:sky/widgets/icon_button.dart'; +export 'package:sky/widgets/ink_well.dart'; +export 'package:sky/widgets/material.dart'; +export 'package:sky/widgets/material_button.dart'; +export 'package:sky/widgets/mimic.dart'; +export 'package:sky/widgets/mimic_overlay.dart'; +export 'package:sky/widgets/mixed_viewport.dart'; +export 'package:sky/widgets/modal_overlay.dart'; +export 'package:sky/widgets/navigator.dart'; +export 'package:sky/widgets/popup_menu.dart'; +export 'package:sky/widgets/popup_menu_item.dart'; +export 'package:sky/widgets/progress_indicator.dart'; +export 'package:sky/widgets/radio.dart'; +export 'package:sky/widgets/raised_button.dart'; +export 'package:sky/widgets/scaffold.dart'; +export 'package:sky/widgets/scrollable.dart'; +export 'package:sky/widgets/snack_bar.dart'; +export 'package:sky/widgets/switch.dart'; +export 'package:sky/widgets/tabs.dart'; +export 'package:sky/widgets/theme.dart'; +export 'package:sky/widgets/title.dart'; +export 'package:sky/widgets/tool_bar.dart'; +export 'package:sky/widgets/transitions.dart'; export 'package:vector_math/vector_math.dart' show Matrix4;