Commit d9916bbb authored by Adam Barth's avatar Adam Barth

Complete the dartdoc for servics.dart (#4383)

Also, add more dartdoc to widgets.dart.
parent ed48c70a
...@@ -2092,7 +2092,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -2092,7 +2092,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// This description is often somewhat long. /// This description is often somewhat long.
/// ///
/// This includes the same information for this RenderObject as given by /// This includes the same information for this RenderObject as given by
/// [toStringDeep()], but does not recurse to any children. /// [toStringDeep], but does not recurse to any children.
String toStringShallow() { String toStringShallow() {
RenderObject debugPreviousActiveLayout = _debugActiveLayout; RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = null; _debugActiveLayout = null;
...@@ -2105,9 +2105,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -2105,9 +2105,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
return result.toString(); return result.toString();
} }
/// Returns a list of strings describing the current node's fields, one field /// Accumulates a list of strings describing the current node's fields, one
/// per string. Subclasses should override this to have their information /// field per string. Subclasses should override this to have their
/// included in toStringDeep(). /// information included in [toStringDeep].
@protected @protected
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
if (debugCreator != null) if (debugCreator != null)
......
...@@ -40,6 +40,8 @@ ActivityProxy _initActivityProxy() { ...@@ -40,6 +40,8 @@ ActivityProxy _initActivityProxy() {
} }
final ActivityProxy _activityProxy = _initActivityProxy(); final ActivityProxy _activityProxy = _initActivityProxy();
/// A singleton for interacting with the current Android activity.
final Activity activity = _activityProxy; final Activity activity = _activityProxy;
Color _cachedPrimaryColor; Color _cachedPrimaryColor;
......
...@@ -15,7 +15,9 @@ mojom.ApplicationMessagesProxy _initHostAppMessagesProxy() { ...@@ -15,7 +15,9 @@ mojom.ApplicationMessagesProxy _initHostAppMessagesProxy() {
final mojom.ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy(); final mojom.ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy();
/// Signature for receiving [HostMessages].
typedef Future<String> HostMessageCallback(String message); typedef Future<String> HostMessageCallback(String message);
typedef Object _SendStringResponseFactory(String response); typedef Object _SendStringResponseFactory(String response);
class _ApplicationMessagesImpl extends mojom.ApplicationMessages { class _ApplicationMessagesImpl extends mojom.ApplicationMessages {
......
...@@ -23,10 +23,14 @@ class Clipboard { ...@@ -23,10 +23,14 @@ class Clipboard {
Clipboard._(); Clipboard._();
/// Stores the given clipboard data on the clipboard.
static void setClipboardData(mojom.ClipboardData clip) { static void setClipboardData(mojom.ClipboardData clip) {
_clipboardProxy.setClipboardData(clip); _clipboardProxy.setClipboardData(clip);
} }
/// Retrieves data from the clipboard that matches the given format.
///
/// * `format` is a media type, such as `text/plain`.
static Future<mojom.ClipboardData> getClipboardData(String format) async { static Future<mojom.ClipboardData> getClipboardData(String format) async {
return (await _clipboardProxy.getClipboardData(format)).clip; return (await _clipboardProxy.getClipboardData(format)).clip;
} }
......
...@@ -8,6 +8,11 @@ import 'dart:ui' as ui show Image, decodeImageFromDataPipe, decodeImageFromList; ...@@ -8,6 +8,11 @@ import 'dart:ui' as ui show Image, decodeImageFromDataPipe, decodeImageFromList;
import 'package:mojo/core.dart' show MojoDataPipeConsumer; import 'package:mojo/core.dart' show MojoDataPipeConsumer;
/// Creates an image from a stream of bytes.
///
/// This function drains the given data pipe and attempts to interpret the bytes
/// in the data pipe as an image. If successful, the returned [Future] resolves
/// to the decoded image. Otherwise, the [Future] resolves to [null].
Future<ui.Image> decodeImageFromDataPipe(MojoDataPipeConsumer consumerHandle) { Future<ui.Image> decodeImageFromDataPipe(MojoDataPipeConsumer consumerHandle) {
Completer<ui.Image> completer = new Completer<ui.Image>(); Completer<ui.Image> completer = new Completer<ui.Image>();
ui.decodeImageFromDataPipe(consumerHandle.handle.h, (ui.Image image) { ui.decodeImageFromDataPipe(consumerHandle.handle.h, (ui.Image image) {
...@@ -16,6 +21,11 @@ Future<ui.Image> decodeImageFromDataPipe(MojoDataPipeConsumer consumerHandle) { ...@@ -16,6 +21,11 @@ Future<ui.Image> decodeImageFromDataPipe(MojoDataPipeConsumer consumerHandle) {
return completer.future; return completer.future;
} }
/// Creates an image from a list of bytes.
///
/// This function attempts to interpret the given bytes an image. If successful,
/// the returned [Future] resolves to the decoded image. Otherwise, the [Future]
/// resolves to [null].
Future<ui.Image> decodeImageFromList(Uint8List list) { Future<ui.Image> decodeImageFromList(Uint8List list) {
Completer<ui.Image> completer = new Completer<ui.Image>(); Completer<ui.Image> completer = new Completer<ui.Image>();
ui.decodeImageFromList(list, (ui.Image image) { ui.decodeImageFromList(list, (ui.Image image) {
......
...@@ -57,6 +57,11 @@ typedef void ImageListener(ImageInfo image); ...@@ -57,6 +57,11 @@ typedef void ImageListener(ImageInfo image);
/// ImageResource objects can also represent an image that hasn't finished /// ImageResource objects can also represent an image that hasn't finished
/// loading. /// loading.
class ImageResource { class ImageResource {
/// Creates an image resource.
///
/// The image resource awaits the given [Future]. When the future resolves,
/// it notifies the [ImageListener]s that have been registered with
/// [addListener].
ImageResource(this._futureImage) { ImageResource(this._futureImage) {
_futureImage.then( _futureImage.then(
_handleImageLoaded, _handleImageLoaded,
......
...@@ -14,17 +14,28 @@ export 'package:sky_services/editing/editing.mojom.dart' show KeyboardType; ...@@ -14,17 +14,28 @@ export 'package:sky_services/editing/editing.mojom.dart' show KeyboardType;
/// ///
/// Most clients will want to use the [keyboard] singleton instance. /// Most clients will want to use the [keyboard] singleton instance.
class Keyboard { class Keyboard {
/// Creates a keyboard that wraps the given keyboard service.
///
/// This constructor is exposed for use by tests. Most non-test clients should
/// use the [keyboard] singleton instance.
Keyboard(this.service); Keyboard(this.service);
// The service is exposed in case you need direct access. /// The underlying keyboard service.
// However, as a general rule, you should be able to do ///
// most of what you need using only this class. /// It is rare to interact with the keyboard service directly. Instead, most
/// clients should interact with the service by first calling [attach] and
/// then using the returned [KeyboardHandle].
final mojom.Keyboard service; final mojom.Keyboard service;
KeyboardHandle _currentHandle; KeyboardHandle _currentHandle;
bool _hidePending = false; bool _hidePending = false;
/// Begin interacting with the keyboard.
///
/// Calling this function helps multiple clients coordinate about which one is
/// currently interacting with the keyboard. The returned [KeyboardHandle]
/// provides interfaces for actually interacting with the keyboard.
KeyboardHandle attach(mojom.KeyboardClientStub stub, mojom.KeyboardConfiguration configuration) { KeyboardHandle attach(mojom.KeyboardClientStub stub, mojom.KeyboardConfiguration configuration) {
assert(stub != null); assert(stub != null);
_currentHandle?.release(); _currentHandle?.release();
...@@ -51,20 +62,35 @@ class Keyboard { ...@@ -51,20 +62,35 @@ class Keyboard {
} }
/// An object that represents a session with the keyboard.
///
/// Keyboard handles are created by the [Keyboard.attach] function. When first
/// created, the keyboard handle is attached to the keyboard as the currently
/// active client. A keyboard handle can become detached either by an explicit
/// calle to [release] or because another client attaches themselves.
class KeyboardHandle { class KeyboardHandle {
KeyboardHandle._(Keyboard keyboard) : _keyboard = keyboard, _attached = true; KeyboardHandle._(Keyboard keyboard) : _keyboard = keyboard, _attached = true;
final Keyboard _keyboard; final Keyboard _keyboard;
bool _attached; /// Whether this handle is currently attached to the keyboard.
///
/// If another client calls [Keyboard.attach], this handle will be marked as
/// no longer attached to the keyboard.
bool get attached => _attached; bool get attached => _attached;
bool _attached;
/// Request that the keyboard become visible (if necesssary).
void show() { void show() {
assert(_attached); assert(_attached);
assert(_keyboard._currentHandle == this); assert(_keyboard._currentHandle == this);
_keyboard.service.show(); _keyboard.service.show();
} }
/// Disclaim interest in the keyboard.
///
/// After calling this function, [attached] will be `false` and the keyboard
/// will disappear (if possible).
void release() { void release() {
if (_attached) { if (_attached) {
assert(_keyboard._currentHandle == this); assert(_keyboard._currentHandle == this);
...@@ -75,6 +101,19 @@ class KeyboardHandle { ...@@ -75,6 +101,19 @@ class KeyboardHandle {
assert(_keyboard._currentHandle != this); assert(_keyboard._currentHandle != this);
} }
/// Changes the keyboard's state.
///
/// The given `state` is uploaded to the keyboard, overwriting whatever state
/// the keyboard had previously.
///
/// Interacting with the keyboard is inherently racy because there are two
/// asynchronous writers: code that wishes to change keyboard state
/// spontaneously (e.g., because the user pasted some text) and the user
/// themselves. For this reason, state set by this function might overwrite
/// state that user has modified in the keyboard that has not yet been
/// reported via the keyboard client.
///
/// Should be called only if `attached` is `true`.
void setEditingState(mojom.EditingState state) { void setEditingState(mojom.EditingState state) {
assert(_attached); assert(_attached);
assert(_keyboard._currentHandle == this); assert(_keyboard._currentHandle == this);
...@@ -87,4 +126,9 @@ mojom.KeyboardProxy _initKeyboardProxy() { ...@@ -87,4 +126,9 @@ mojom.KeyboardProxy _initKeyboardProxy() {
} }
final mojom.KeyboardProxy _keyboardProxy = _initKeyboardProxy(); final mojom.KeyboardProxy _keyboardProxy = _initKeyboardProxy();
/// A singleton for managing interactions with the keyboard.
///
/// You can begin a session with the keyboard by calling the [Keyboard.attach]
/// method on this object.
final Keyboard keyboard = new Keyboard(_keyboardProxy); final Keyboard keyboard = new Keyboard(_keyboardProxy);
...@@ -255,12 +255,18 @@ void debugDumpApp() { ...@@ -255,12 +255,18 @@ void debugDumpApp() {
debugPrint(WidgetsBinding.instance.renderViewElement.toStringDeep()); debugPrint(WidgetsBinding.instance.renderViewElement.toStringDeep());
} }
/// This class provides a bridge from a RenderObject to an Element tree. The /// A bridge from a [RenderObject] to an [Element] tree.
/// given container is the RenderObject that the Element tree should be inserted ///
/// into. It must be a RenderObject that implements the /// The given container is the [RenderObject] that the [Element] tree should be
/// RenderObjectWithChildMixin protocol. The type argument T is the kind of /// inserted into. It must be a [RenderObject] that implements the
/// RenderObject that the container expects as its child. /// [RenderObjectWithChildMixin] protocol. The type argument `T` is the kind of
/// [RenderObject] that the container expects as its child.
///
/// Used by [runApp] to bootstrap applications.
class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget { class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget {
/// Creates a bridge from a [RenderObject] to an [Element] tree.
///
/// Used by [WidgetsBinding] to attach the root widget to the [RenderView].
RenderObjectToWidgetAdapter({ RenderObjectToWidgetAdapter({
this.child, this.child,
RenderObjectWithChildMixin<T> container, RenderObjectWithChildMixin<T> container,
...@@ -270,8 +276,10 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi ...@@ -270,8 +276,10 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
final Widget child; final Widget child;
/// The [RenderObject] that is the parent of the [Element] created by this widget.
final RenderObjectWithChildMixin<T> container; final RenderObjectWithChildMixin<T> container;
/// A short description of this widget used by debugging aids.
final String debugShortDescription; final String debugShortDescription;
@override @override
...@@ -283,6 +291,12 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi ...@@ -283,6 +291,12 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
@override @override
void updateRenderObject(BuildContext context, RenderObject renderObject) { } void updateRenderObject(BuildContext context, RenderObject renderObject) { }
/// Inflate this widget and actually set the resulting [RenderObject] as the child of [container].
///
/// If `element` is null, this function will create a new element. Otherwise,
/// the given element will be updated with this widget.
///
/// Used by [runApp] to bootstrap applications.
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [RenderObjectToWidgetElement<T> element]) { RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [RenderObjectToWidgetElement<T> element]) {
owner.lockState(() { owner.lockState(() {
if (element == null) { if (element == null) {
...@@ -300,15 +314,22 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi ...@@ -300,15 +314,22 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
String toStringShort() => debugShortDescription ?? super.toStringShort(); String toStringShort() => debugShortDescription ?? super.toStringShort();
} }
/// This element class is the instantiation of a [RenderObjectToWidgetAdapter]. /// A [RootRenderObjectElement] that is hosted by a [RenderObject].
/// It can only be used as the root of an Element tree (it cannot be mounted ///
/// into another Element, it's parent must be null). /// This element class is the instantiation of a [RenderObjectToWidgetAdapter]
/// widget. It can be used only as the root of an [Element] tree (it cannot be
/// mounted into another [Element]; it's parent must be null).
/// ///
/// In typical usage, it will be instantiated for a RenderObjectToWidgetAdapter /// In typical usage, it will be instantiated for a [RenderObjectToWidgetAdapter]
/// whose container is the RenderView that connects to the Flutter engine. In /// whose container is the [RenderView] that connects to the Flutter engine. In
/// this usage, it is normally instantiated by the bootstrapping logic in the /// this usage, it is normally instantiated by the bootstrapping logic in the
/// WidgetsFlutterBinding singleton created by runApp(). /// [WidgetsFlutterBinding] singleton created by [runApp].
class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObjectElement { class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObjectElement {
/// Creates an element that is hosted by a [RenderObject].
///
/// The [RenderObject] created by this element is not automatically set as a
/// child of the hosting [RenderObject]. To actually attach this element to
/// the render tree, call [RenderObjectToWidgetAdapter.attachToRenderTree].
RenderObjectToWidgetElement(RenderObjectToWidgetAdapter<T> widget) : super(widget); RenderObjectToWidgetElement(RenderObjectToWidgetAdapter<T> widget) : super(widget);
@override @override
......
...@@ -9,9 +9,15 @@ import 'media_query.dart'; ...@@ -9,9 +9,15 @@ import 'media_query.dart';
export 'package:flutter/rendering.dart' show ChildViewConnection; export 'package:flutter/rendering.dart' show ChildViewConnection;
/// (mojo-only) A widget that is replaced by content from another process.
///
/// Requires a [MediaQuery] ancestor to provide appropriate media information to
/// the child.
class ChildView extends StatelessWidget { class ChildView extends StatelessWidget {
/// Creates a widget that is replaced by content from another process.
ChildView({ Key key, this.child }) : super(key: key); ChildView({ Key key, this.child }) : super(key: key);
/// A connection to the child whose content will replace this widget.
final ChildViewConnection child; final ChildViewConnection child;
@override @override
......
...@@ -2,30 +2,42 @@ ...@@ -2,30 +2,42 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart'; import 'framework.dart';
import 'scrollable.dart'; import 'scrollable.dart';
/// Signature for building the contents of a scrollable widget.
///
/// Typically returns a tree of widgets that includes the viewport that will be
/// scrolled to the given `scrollOffset`.
typedef Widget ViewportBuilder(BuildContext context, ScrollableState state, double scrollOffset); typedef Widget ViewportBuilder(BuildContext context, ScrollableState state, double scrollOffset);
/// If true, the ClampOverscroll's [Scrollable] descendant will clamp its /// A widget that controls whether [Scrollable] descendants will overscroll.
///
/// If `true`, the ClampOverscroll's [Scrollable] descendant will clamp its
/// viewport's scrollOffsets to the [ScrollBehavior]'s min and max values. /// viewport's scrollOffsets to the [ScrollBehavior]'s min and max values.
/// In this case the Scrollable's scrollOffset will still over- and undershoot /// In this case the Scrollable's scrollOffset will still over- and undershoot
/// the ScrollBehavior's limits, but the viewport itself will not. /// the ScrollBehavior's limits, but the viewport itself will not.
class ClampOverscrolls extends InheritedWidget { class ClampOverscrolls extends InheritedWidget {
/// Creates a widget that controls whether [Scrollable] descendants will overscroll.
///
/// The [value] and [child] arguments must not be null.
ClampOverscrolls({ ClampOverscrolls({
Key key, Key key,
this.value, @required this.value,
Widget child @required Widget child
}) : super(key: key, child: child) { }) : super(key: key, child: child) {
assert(value != null); assert(value != null);
assert(child != null); assert(child != null);
} }
/// True if the [Scrollable] descendant should clamp its viewport's scrollOffset /// Whether [Scrollable] descendants should clamp their viewport's
/// values when they are less than the [ScrollBehavior]'s minimum or greater than /// scrollOffset values when they are less than the [ScrollBehavior]'s minimum
/// its maximum. /// or greater than its maximum.
final bool value; final bool value;
/// Whether a [Scrollable] widget within the given context should overscroll.
static bool of(BuildContext context) { static bool of(BuildContext context) {
final ClampOverscrolls result = context.inheritFromWidgetOfExactType(ClampOverscrolls); final ClampOverscrolls result = context.inheritFromWidgetOfExactType(ClampOverscrolls);
return result?.value ?? false; return result?.value ?? false;
...@@ -48,7 +60,6 @@ class ClampOverscrolls extends InheritedWidget { ...@@ -48,7 +60,6 @@ class ClampOverscrolls extends InheritedWidget {
return viewport; return viewport;
} }
@override @override
bool updateShouldNotify(ClampOverscrolls old) => value != old.value; bool updateShouldNotify(ClampOverscrolls old) => value != old.value;
......
...@@ -101,6 +101,12 @@ bool debugCheckHasTable(BuildContext context) { ...@@ -101,6 +101,12 @@ bool debugCheckHasTable(BuildContext context) {
return true; return true;
} }
/// Asserts that the `built` widget is not null.
///
/// Used when the given `widget` calls a builder function to check that the
/// function returned a non-null value, as typically required.
///
/// Does nothing when asserts are disabled.
void debugWidgetBuilderValue(Widget widget, Widget built) { void debugWidgetBuilderValue(Widget widget, Widget built) {
assert(() { assert(() {
if (built == null) { if (built == null) {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'transitions.dart'; import 'transitions.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -14,6 +16,7 @@ const double _kMinFlingVelocityDelta = 400.0; ...@@ -14,6 +16,7 @@ const double _kMinFlingVelocityDelta = 400.0;
const double _kFlingVelocityScale = 1.0 / 300.0; const double _kFlingVelocityScale = 1.0 / 300.0;
const double _kDismissThreshold = 0.4; const double _kDismissThreshold = 0.4;
/// Signature used by [Dismissable] to indicate that it has been dismissed in the given `direction`.
typedef void DismissDirectionCallback(DismissDirection direction); typedef void DismissDirectionCallback(DismissDirection direction);
/// The direction in which a [Dismissable] can be dismissed. /// The direction in which a [Dismissable] can be dismissed.
...@@ -39,7 +42,7 @@ enum DismissDirection { ...@@ -39,7 +42,7 @@ enum DismissDirection {
down down
} }
/// Can be dismissed by dragging in the indicated [direction]. /// A widget that can be dismissed by dragging in the indicated [direction].
/// ///
/// Dragging or flinging this widget in the [DismissDirection] causes the child /// Dragging or flinging this widget in the [DismissDirection] causes the child
/// to slide out of view. Following the slide animation, if [resizeDuration] is /// to slide out of view. Following the slide animation, if [resizeDuration] is
...@@ -56,8 +59,16 @@ enum DismissDirection { ...@@ -56,8 +59,16 @@ enum DismissDirection {
/// list item, it must have a key that distinguishes it from the other items and /// list item, it must have a key that distinguishes it from the other items and
/// its [onDismissed] callback must remove the item from the list. /// its [onDismissed] callback must remove the item from the list.
class Dismissable extends StatefulWidget { class Dismissable extends StatefulWidget {
/// Creates a widget that can be dismissed.
///
/// The [key] argument must not be null because [Dismissable]s are commonly
/// used in lists and removed from the list when dismissed. Without keys, the
/// default behavior is to sync widgets based on their index in the list,
/// which means the item after the dismissed item would be synced with the
/// state of the dismissed item. Using keys causes the widgets to sync
/// according to their keys and avoids this pitfall.
Dismissable({ Dismissable({
Key key, @required Key key,
this.child, this.child,
this.background, this.background,
this.secondaryBackground, this.secondaryBackground,
......
...@@ -5,18 +5,29 @@ ...@@ -5,18 +5,29 @@
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'binding.dart'; import 'binding.dart';
import 'framework.dart'; import 'framework.dart';
import 'overlay.dart'; import 'overlay.dart';
/// Signature for determining whether the given data will be accepted by a [DragTarget].
typedef bool DragTargetWillAccept<T>(T data); typedef bool DragTargetWillAccept<T>(T data);
/// Signature for causing a [DragTarget] to accept the given data.
typedef void DragTargetAccept<T>(T data); typedef void DragTargetAccept<T>(T data);
/// Signature for building children of a [DragTarget].
///
/// The `candidateData` argument contains the list of drag data that is hovering
/// over this [DragTarget] and that has passed [DragTarget.onWillAccept]. The
/// `rejectedData` argument contains the list of drag data that is hovering over
/// this [DragTarget] and that will not be accepted by the [DragTarget].
typedef Widget DragTargetBuilder<T>(BuildContext context, List<T> candidateData, List<dynamic> rejectedData); typedef Widget DragTargetBuilder<T>(BuildContext context, List<T> candidateData, List<dynamic> rejectedData);
/// Called when a [Draggable] is dropped without being accepted by a [DragTarget]. /// Signature for when a [Draggable] is dropped without being accepted by a [DragTarget].
typedef void OnDraggableCanceled(Velocity velocity, Offset offset); typedef void DraggableCanceledCallback(Velocity velocity, Offset offset);
/// Where the [Draggable] should be anchored during a drag. /// Where the [Draggable] should be anchored during a drag.
enum DragAnchor { enum DragAnchor {
...@@ -40,12 +51,16 @@ enum DragAnchor { ...@@ -40,12 +51,16 @@ enum DragAnchor {
/// Subclass this widget to customize the gesture used to start a drag. /// Subclass this widget to customize the gesture used to start a drag.
abstract class DraggableBase<T> extends StatefulWidget { abstract class DraggableBase<T> extends StatefulWidget {
/// Initializes fields for subclasses.
///
/// The [child] and [feedback] arguments must not be null. If
/// [maxSimultaneousDrags] is non-null, it must be positive.
DraggableBase({ DraggableBase({
Key key, Key key,
@required this.child,
@required this.feedback,
this.data, this.data,
this.child,
this.childWhenDragging, this.childWhenDragging,
this.feedback,
this.feedbackOffset: Offset.zero, this.feedbackOffset: Offset.zero,
this.dragAnchor: DragAnchor.child, this.dragAnchor: DragAnchor.child,
this.maxSimultaneousDrags, this.maxSimultaneousDrags,
...@@ -56,6 +71,7 @@ abstract class DraggableBase<T> extends StatefulWidget { ...@@ -56,6 +71,7 @@ abstract class DraggableBase<T> extends StatefulWidget {
assert(maxSimultaneousDrags == null || maxSimultaneousDrags > 0); assert(maxSimultaneousDrags == null || maxSimultaneousDrags > 0);
} }
/// The data that will be dropped by this draggable.
final T data; final T data;
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
...@@ -85,7 +101,7 @@ abstract class DraggableBase<T> extends StatefulWidget { ...@@ -85,7 +101,7 @@ abstract class DraggableBase<T> extends StatefulWidget {
final int maxSimultaneousDrags; final int maxSimultaneousDrags;
/// Called when the draggable is dropped without being accepted by a [DragTarget]. /// Called when the draggable is dropped without being accepted by a [DragTarget].
final OnDraggableCanceled onDraggableCanceled; final DraggableCanceledCallback onDraggableCanceled;
/// Should return a new MultiDragGestureRecognizer instance /// Should return a new MultiDragGestureRecognizer instance
/// constructed with the given arguments. /// constructed with the given arguments.
...@@ -97,22 +113,26 @@ abstract class DraggableBase<T> extends StatefulWidget { ...@@ -97,22 +113,26 @@ abstract class DraggableBase<T> extends StatefulWidget {
/// Makes its child draggable starting from tap down. /// Makes its child draggable starting from tap down.
class Draggable<T> extends DraggableBase<T> { class Draggable<T> extends DraggableBase<T> {
/// Creates a widget that can be dragged starting from tap down.
///
/// The [child] and [feedback] arguments must not be null. If
/// [maxSimultaneousDrags] is non-null, it must be positive.
Draggable({ Draggable({
Key key, Key key,
@required Widget child,
@required Widget feedback,
T data, T data,
Widget child,
Widget childWhenDragging, Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero, Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child, DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags, int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled DraggableCanceledCallback onDraggableCanceled
}) : super( }) : super(
key: key, key: key,
data: data,
child: child, child: child,
childWhenDragging: childWhenDragging,
feedback: feedback, feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor, dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags, maxSimultaneousDrags: maxSimultaneousDrags,
...@@ -128,22 +148,26 @@ class Draggable<T> extends DraggableBase<T> { ...@@ -128,22 +148,26 @@ class Draggable<T> extends DraggableBase<T> {
/// Makes its child draggable. When competing with other gestures, /// Makes its child draggable. When competing with other gestures,
/// this will only start the drag horizontally. /// this will only start the drag horizontally.
class HorizontalDraggable<T> extends DraggableBase<T> { class HorizontalDraggable<T> extends DraggableBase<T> {
/// Creates a widget that can be dragged.
///
/// The [child] and [feedback] arguments must not be null. If
/// [maxSimultaneousDrags] is non-null, it must be positive.
HorizontalDraggable({ HorizontalDraggable({
Key key, Key key,
@required Widget child,
@required Widget feedback,
T data, T data,
Widget child,
Widget childWhenDragging, Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero, Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child, DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags, int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled DraggableCanceledCallback onDraggableCanceled
}) : super( }) : super(
key: key, key: key,
data: data,
child: child, child: child,
childWhenDragging: childWhenDragging,
feedback: feedback, feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor, dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags, maxSimultaneousDrags: maxSimultaneousDrags,
...@@ -159,22 +183,26 @@ class HorizontalDraggable<T> extends DraggableBase<T> { ...@@ -159,22 +183,26 @@ class HorizontalDraggable<T> extends DraggableBase<T> {
/// Makes its child draggable. When competing with other gestures, /// Makes its child draggable. When competing with other gestures,
/// this will only start the drag vertically. /// this will only start the drag vertically.
class VerticalDraggable<T> extends DraggableBase<T> { class VerticalDraggable<T> extends DraggableBase<T> {
/// Creates a widget that can be dragged.
///
/// The [child] and [feedback] arguments must not be null. If
/// [maxSimultaneousDrags] is non-null, it must be positive.
VerticalDraggable({ VerticalDraggable({
Key key, Key key,
@required Widget child,
@required Widget feedback,
T data, T data,
Widget child,
Widget childWhenDragging, Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero, Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child, DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags, int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled DraggableCanceledCallback onDraggableCanceled
}) : super( }) : super(
key: key, key: key,
data: data,
child: child, child: child,
childWhenDragging: childWhenDragging,
feedback: feedback, feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor, dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags, maxSimultaneousDrags: maxSimultaneousDrags,
...@@ -189,22 +217,26 @@ class VerticalDraggable<T> extends DraggableBase<T> { ...@@ -189,22 +217,26 @@ class VerticalDraggable<T> extends DraggableBase<T> {
/// Makes its child draggable starting from long press. /// Makes its child draggable starting from long press.
class LongPressDraggable<T> extends DraggableBase<T> { class LongPressDraggable<T> extends DraggableBase<T> {
/// Creates a widget that can be dragged starting from long press.
///
/// The [child] and [feedback] arguments must not be null. If
/// [maxSimultaneousDrags] is non-null, it must be positive.
LongPressDraggable({ LongPressDraggable({
Key key, Key key,
@required Widget child,
@required Widget feedback,
T data, T data,
Widget child,
Widget childWhenDragging, Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero, Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child, DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags, int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled DraggableCanceledCallback onDraggableCanceled
}) : super( }) : super(
key: key, key: key,
data: data,
child: child, child: child,
childWhenDragging: childWhenDragging,
feedback: feedback, feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor, dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags, maxSimultaneousDrags: maxSimultaneousDrags,
...@@ -224,7 +256,6 @@ class LongPressDraggable<T> extends DraggableBase<T> { ...@@ -224,7 +256,6 @@ class LongPressDraggable<T> extends DraggableBase<T> {
} }
class _DraggableState<T> extends State<DraggableBase<T>> { class _DraggableState<T> extends State<DraggableBase<T>> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
...@@ -286,11 +317,14 @@ class _DraggableState<T> extends State<DraggableBase<T>> { ...@@ -286,11 +317,14 @@ class _DraggableState<T> extends State<DraggableBase<T>> {
} }
} }
/// Receives data when a [Draggable] widget is dropped. /// A widget that receives data when a [Draggable] widget is dropped.
class DragTarget<T> extends StatefulWidget { class DragTarget<T> extends StatefulWidget {
/// Creates a widget that receives drags.
///
/// The [builder] argument must not be null.
const DragTarget({ const DragTarget({
Key key, Key key,
this.builder, @required this.builder,
this.onWillAccept, this.onWillAccept,
this.onAccept this.onAccept
}) : super(key: key); }) : super(key: key);
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/rendering.dart' show RenderEditableLine, SelectionChangedHandler; import 'package:flutter/rendering.dart' show RenderEditableLine, SelectionChangedHandler;
import 'package:sky_services/editing/editing.mojom.dart' as mojom;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:sky_services/editing/editing.mojom.dart' as mojom;
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -85,8 +86,17 @@ class _KeyboardClientImpl implements mojom.KeyboardClient { ...@@ -85,8 +86,17 @@ class _KeyboardClientImpl implements mojom.KeyboardClient {
} }
} }
/// Configurable state of an input field. /// Configuration information for an input field.
///
/// An [InputValue] contains the text for the input field as well as the
/// selection extent and the composing range.
class InputValue { class InputValue {
/// Creates configuration information for an input field
///
/// The selection and composing range must be within the text.
///
/// The [text], [selection], and [composing] arguments must not be null but
/// each have default values.
const InputValue({ const InputValue({
this.text: '', this.text: '',
this.selection: const TextSelection.collapsed(offset: -1), this.selection: const TextSelection.collapsed(offset: -1),
...@@ -99,9 +109,10 @@ class InputValue { ...@@ -99,9 +109,10 @@ class InputValue {
/// The range of text that is currently selected. /// The range of text that is currently selected.
final TextSelection selection; final TextSelection selection;
// The range of text that is still being composed. /// The range of text that is still being composed.
final TextRange composing; final TextRange composing;
/// An input value that corresponds to the empty string with no selection and no composing range.
static const InputValue empty = const InputValue(); static const InputValue empty = const InputValue();
@override @override
...@@ -145,9 +156,12 @@ class InputValue { ...@@ -145,9 +156,12 @@ class InputValue {
/// This control is not intended to be used directly. Instead, consider using /// This control is not intended to be used directly. Instead, consider using
/// [Input], which provides focus management and material design. /// [Input], which provides focus management and material design.
class RawInputLine extends Scrollable { class RawInputLine extends Scrollable {
/// Creates a basic single-line input control.
///
/// The [value] argument must not be null.
RawInputLine({ RawInputLine({
Key key, Key key,
this.value, @required this.value,
this.focusKey, this.focusKey,
this.hideText: false, this.hideText: false,
this.style, this.style,
...@@ -162,7 +176,9 @@ class RawInputLine extends Scrollable { ...@@ -162,7 +176,9 @@ class RawInputLine extends Scrollable {
key: key, key: key,
initialScrollOffset: 0.0, initialScrollOffset: 0.0,
scrollDirection: Axis.horizontal scrollDirection: Axis.horizontal
); ) {
assert(value != null);
}
/// The string being displayed in this widget. /// The string being displayed in this widget.
final InputValue value; final InputValue value;
...@@ -203,6 +219,7 @@ class RawInputLine extends Scrollable { ...@@ -203,6 +219,7 @@ class RawInputLine extends Scrollable {
RawInputLineState createState() => new RawInputLineState(); RawInputLineState createState() => new RawInputLineState();
} }
/// State for a [RawInputLine].
class RawInputLineState extends ScrollableState<RawInputLine> { class RawInputLineState extends ScrollableState<RawInputLine> {
Timer _cursorTimer; Timer _cursorTimer;
bool _showCursor = false; bool _showCursor = false;
...@@ -276,6 +293,13 @@ class RawInputLineState extends ScrollableState<RawInputLine> { ...@@ -276,6 +293,13 @@ class RawInputLineState extends ScrollableState<RawInputLine> {
} }
} }
/// Express interest in interacting with the keyboard.
///
/// If this control is already attached to the keyboard, this function will
/// request that the keyboard become visible. Otherwise, this function will
/// ask the focus system that it become focused. If successful in acquiring
/// focus, the control will then attach to the keyboard and request that the
/// keyboard become visible.
void requestKeyboard() { void requestKeyboard() {
if (_isAttachedToKeyboard) { if (_isAttachedToKeyboard) {
_keyboardHandle.show(); _keyboardHandle.show();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
import 'media_query.dart'; import 'media_query.dart';
...@@ -94,8 +96,11 @@ class _FocusScope extends InheritedWidget { ...@@ -94,8 +96,11 @@ class _FocusScope extends InheritedWidget {
/// widgets), then the widget this this global key actually has the focus in the /// widgets), then the widget this this global key actually has the focus in the
/// entire system. /// entire system.
class Focus extends StatefulWidget { class Focus extends StatefulWidget {
/// Creates a scope for managing focus.
///
/// The [key] argument must not be null.
Focus({ Focus({
GlobalKey key, @required GlobalKey key,
this.child this.child
}) : super(key: key) { }) : super(key: key) {
assert(key != null); assert(key != null);
......
...@@ -2,14 +2,20 @@ ...@@ -2,14 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
/// A container for grouping together multiple form field widgets (e.g. Input). /// A container for grouping together multiple form field widgets (e.g.
/// [Input] widgets).
class Form extends StatefulWidget { class Form extends StatefulWidget {
/// Creates a container for form fields.
///
/// The [child] argument must not be null.
Form({ Form({
Key key, Key key,
this.child, @required this.child,
this.onSubmitted this.onSubmitted
}) : super(key: key) { }) : super(key: key) {
assert(child != null); assert(child != null);
...@@ -28,7 +34,7 @@ class Form extends StatefulWidget { ...@@ -28,7 +34,7 @@ class Form extends StatefulWidget {
class _FormState extends State<Form> { class _FormState extends State<Form> {
int generation = 0; int generation = 0;
void onFieldChanged() { void _onFieldChanged() {
setState(() { setState(() {
++generation; ++generation;
}); });
...@@ -36,20 +42,23 @@ class _FormState extends State<Form> { ...@@ -36,20 +42,23 @@ class _FormState extends State<Form> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new FormScope( return new FormScope._(
state: this, formState: this,
generation: generation, generation: generation,
child: config.child child: config.child
); );
} }
} }
/// Signature for validating a form field.
typedef String FormFieldValidator<T>(T value); typedef String FormFieldValidator<T>(T value);
/// Signature for being notified when a form field changes value.
typedef void FormFieldSetter<T>(T newValue); typedef void FormFieldSetter<T>(T newValue);
/// This contains identifying information for Input fields, required if the /// Identifying information for form controls.
/// Input is part of a Form.
class FormField<T> { class FormField<T> {
/// Creates identifying information for form controls
FormField({ FormField({
this.setter, this.setter,
this.validator this.validator
...@@ -63,29 +72,32 @@ class FormField<T> { ...@@ -63,29 +72,32 @@ class FormField<T> {
final FormFieldValidator<T> validator; final FormFieldValidator<T> validator;
} }
/// The root of all Forms. Used by form field widgets (e.g. Input) to /// A widget that establishes a scope for a [Form].
/// communicate changes back to the client. ///
/// Cannot be created directly. Instead, create a [Form] widget, which builds
/// a [FormScope].
///
/// Useful for locating the closest enclosing [Form].
class FormScope extends InheritedWidget { class FormScope extends InheritedWidget {
FormScope({ FormScope._({
Key key, Key key,
Widget child, Widget child,
_FormState state, _FormState formState,
int generation int generation
}) : _state = state, }) : _formState = formState,
_generation = generation, _generation = generation,
super(key: key, child: child); super(key: key, child: child);
final _FormState _state; final _FormState _formState;
/// Incremented every time a form field has changed. This lets us know when /// Incremented every time a form field has changed. This lets us know when
/// to rebuild the form. /// to rebuild the form.
final int _generation; final int _generation;
/// The Form this widget belongs to. /// The [Form] associated with this widget.
Form get form => _state.config; Form get form => _formState.config;
/// Finds the FormScope that encloses the widget being built from the given /// The closest [FormScope] encloses the given context.
/// context.
static FormScope of(BuildContext context) { static FormScope of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FormScope); return context.inheritFromWidgetOfExactType(FormScope);
} }
...@@ -93,7 +105,7 @@ class FormScope extends InheritedWidget { ...@@ -93,7 +105,7 @@ class FormScope extends InheritedWidget {
/// Use this to notify the Form that a form field has changed. This will /// Use this to notify the Form that a form field has changed. This will
/// cause all form fields to rebuild, useful if form fields have /// cause all form fields to rebuild, useful if form fields have
/// interdependencies. /// interdependencies.
void onFieldChanged() => _state.onFieldChanged(); void onFieldChanged() => _formState._onFieldChanged();
@override @override
bool updateShouldNotify(FormScope old) => _generation != old._generation; bool updateShouldNotify(FormScope old) => _generation != old._generation;
......
...@@ -28,6 +28,10 @@ export 'package:flutter/gestures.dart' show ...@@ -28,6 +28,10 @@ export 'package:flutter/gestures.dart' show
GestureScaleEndCallback, GestureScaleEndCallback,
Velocity; Velocity;
/// Signature for creating gesture recognizers.
///
/// The `recognizer` argument is the gesture recognizer that currently occupies
/// the slot for which a gesture recognizer is being created.
typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer); typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer);
/// A widget that detects gestures. /// A widget that detects gestures.
...@@ -40,6 +44,17 @@ typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer) ...@@ -40,6 +44,17 @@ typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer)
/// ///
/// See http://flutter.io/gestures/ for additional information. /// See http://flutter.io/gestures/ for additional information.
class GestureDetector extends StatelessWidget { class GestureDetector extends StatelessWidget {
/// Creates a widget that detects gestures.
///
/// Pan and scale callbacks cannot be used simultaneously because scale is a
/// superset of pan. Simply use the scale callbacks instead.
///
/// Horizontal and vertical drag callbacks cannot be used simultaneously
/// because a combination of a horizontal and vertical drag is a pan. Simply
/// use the pan callbacks instead.
///
/// By default, gesture detectors contribute semantic information to the tree
/// that is used by assistive technology.
GestureDetector({ GestureDetector({
Key key, Key key,
this.child, this.child,
...@@ -296,6 +311,10 @@ class GestureDetector extends StatelessWidget { ...@@ -296,6 +311,10 @@ class GestureDetector extends StatelessWidget {
/// RawGestureDetector is useful primarily when developing your /// RawGestureDetector is useful primarily when developing your
/// own gesture recognizers. /// own gesture recognizers.
class RawGestureDetector extends StatefulWidget { class RawGestureDetector extends StatefulWidget {
/// Creates a widget that detects gestures.
///
/// By default, gesture detectors contribute semantic information to the tree
/// that is used by assistive technology.
RawGestureDetector({ RawGestureDetector({
Key key, Key key,
this.child, this.child,
...@@ -310,6 +329,7 @@ class RawGestureDetector extends StatefulWidget { ...@@ -310,6 +329,7 @@ class RawGestureDetector extends StatefulWidget {
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
final Widget child; final Widget child;
/// The gestures that this widget will attempt to recognize.
final Map<Type, GestureRecognizerFactory> gestures; final Map<Type, GestureRecognizerFactory> gestures;
/// How this gesture detector should behave during hit testing. /// How this gesture detector should behave during hit testing.
...@@ -326,8 +346,8 @@ class RawGestureDetector extends StatefulWidget { ...@@ -326,8 +346,8 @@ class RawGestureDetector extends StatefulWidget {
RawGestureDetectorState createState() => new RawGestureDetectorState(); RawGestureDetectorState createState() => new RawGestureDetectorState();
} }
/// State for a [RawGestureDetector].
class RawGestureDetectorState extends State<RawGestureDetector> { class RawGestureDetectorState extends State<RawGestureDetector> {
Map<Type, GestureRecognizer> _recognizers = const <Type, GestureRecognizer>{}; Map<Type, GestureRecognizer> _recognizers = const <Type, GestureRecognizer>{};
@override @override
......
...@@ -47,9 +47,11 @@ class _GridPaperPainter extends CustomPainter { ...@@ -47,9 +47,11 @@ class _GridPaperPainter extends CustomPainter {
bool hitTest(Point position) => false; bool hitTest(Point position) => false;
} }
/// Draws a rectalinear grid of 1px width lines at the specified color and interval. /// A widget that draws a rectilinear grid of 1px wide lines.
/// Useful with a Stack for visualizing your layout along a grid. ///
/// Useful with a [Stack] for visualizing your layout along a grid.
class GridPaper extends StatelessWidget { class GridPaper extends StatelessWidget {
/// Creates a widget that draws a rectilinear grid of 1px wide lines.
GridPaper({ GridPaper({
Key key, Key key,
this.color: const Color(0x7FC3E8F3), this.color: const Color(0x7FC3E8F3),
......
...@@ -5,10 +5,14 @@ ...@@ -5,10 +5,14 @@
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
import 'package:meta/meta.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
/// An interpolation between two [BoxConstraint]s. /// An interpolation between two [BoxConstraint]s.
class BoxConstraintsTween extends Tween<BoxConstraints> { class BoxConstraintsTween extends Tween<BoxConstraints> {
/// Creates a box constraints tween.
///
/// The [begin] and [end] arguments must not be null.
BoxConstraintsTween({ BoxConstraints begin, BoxConstraints end }) : super(begin: begin, end: end); BoxConstraintsTween({ BoxConstraints begin, BoxConstraints end }) : super(begin: begin, end: end);
@override @override
...@@ -17,6 +21,9 @@ class BoxConstraintsTween extends Tween<BoxConstraints> { ...@@ -17,6 +21,9 @@ class BoxConstraintsTween extends Tween<BoxConstraints> {
/// An interpolation between two [Decoration]s. /// An interpolation between two [Decoration]s.
class DecorationTween extends Tween<Decoration> { class DecorationTween extends Tween<Decoration> {
/// Creates a decoration tween.
///
/// The [begin] and [end] arguments must not be null.
DecorationTween({ Decoration begin, Decoration end }) : super(begin: begin, end: end); DecorationTween({ Decoration begin, Decoration end }) : super(begin: begin, end: end);
@override @override
...@@ -25,6 +32,9 @@ class DecorationTween extends Tween<Decoration> { ...@@ -25,6 +32,9 @@ class DecorationTween extends Tween<Decoration> {
/// An interpolation between two [EdgeInsets]s. /// An interpolation between two [EdgeInsets]s.
class EdgeInsetsTween extends Tween<EdgeInsets> { class EdgeInsetsTween extends Tween<EdgeInsets> {
/// Creates an edge insets tween.
///
/// The [begin] and [end] arguments must not be null.
EdgeInsetsTween({ EdgeInsets begin, EdgeInsets end }) : super(begin: begin, end: end); EdgeInsetsTween({ EdgeInsets begin, EdgeInsets end }) : super(begin: begin, end: end);
@override @override
...@@ -35,12 +45,15 @@ class EdgeInsetsTween extends Tween<EdgeInsets> { ...@@ -35,12 +45,15 @@ class EdgeInsetsTween extends Tween<EdgeInsets> {
/// ///
/// Currently this class works only for translations. /// Currently this class works only for translations.
class Matrix4Tween extends Tween<Matrix4> { class Matrix4Tween extends Tween<Matrix4> {
/// Creates a [Matrix4] tween.
///
/// The [begin] and [end] arguments must not be null.
Matrix4Tween({ Matrix4 begin, Matrix4 end }) : super(begin: begin, end: end); Matrix4Tween({ Matrix4 begin, Matrix4 end }) : super(begin: begin, end: end);
@override @override
Matrix4 lerp(double t) { Matrix4 lerp(double t) {
// TODO(mpcomplete): Animate the full matrix. Will animating the cells // TODO(abarth): We should use [Matrix4.decompose] and animate the
// separately work? // decomposed parameters instead of just animating the translation.
Vector3 beginT = begin.getTranslation(); Vector3 beginT = begin.getTranslation();
Vector3 endT = end.getTranslation(); Vector3 endT = end.getTranslation();
Vector3 lerpT = beginT*(1.0-t) + endT*t; Vector3 lerpT = beginT*(1.0-t) + endT*t;
...@@ -52,6 +65,9 @@ class Matrix4Tween extends Tween<Matrix4> { ...@@ -52,6 +65,9 @@ class Matrix4Tween extends Tween<Matrix4> {
/// ///
/// This will not work well if the styles don't set the same fields. /// This will not work well if the styles don't set the same fields.
class TextStyleTween extends Tween<TextStyle> { class TextStyleTween extends Tween<TextStyle> {
/// Creates a text style tween.
///
/// The [begin] and [end] arguments must not be null.
TextStyleTween({ TextStyle begin, TextStyle end }) : super(begin: begin, end: end); TextStyleTween({ TextStyle begin, TextStyle end }) : super(begin: begin, end: end);
@override @override
...@@ -61,10 +77,13 @@ class TextStyleTween extends Tween<TextStyle> { ...@@ -61,10 +77,13 @@ class TextStyleTween extends Tween<TextStyle> {
/// An abstract widget for building widgets that gradually change their /// An abstract widget for building widgets that gradually change their
/// values over a period of time. /// values over a period of time.
abstract class ImplicitlyAnimatedWidget extends StatefulWidget { abstract class ImplicitlyAnimatedWidget extends StatefulWidget {
/// Initializes fields for subclasses.
///
/// The [curve] and [duration] arguments must not be null.
ImplicitlyAnimatedWidget({ ImplicitlyAnimatedWidget({
Key key, Key key,
this.curve: Curves.linear, this.curve: Curves.linear,
this.duration @required this.duration
}) : super(key: key) { }) : super(key: key) {
assert(curve != null); assert(curve != null);
assert(duration != null); assert(duration != null);
...@@ -196,6 +215,9 @@ abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> exten ...@@ -196,6 +215,9 @@ abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> exten
/// likely want to use a subclass of [Transition] or use an /// likely want to use a subclass of [Transition] or use an
/// [AnimationController] yourself. /// [AnimationController] yourself.
class AnimatedContainer extends ImplicitlyAnimatedWidget { class AnimatedContainer extends ImplicitlyAnimatedWidget {
/// Creates a container that animates its parameters implicitly.
///
/// The [curve] and [duration] arguments must not be null.
AnimatedContainer({ AnimatedContainer({
Key key, Key key,
this.child, this.child,
...@@ -208,7 +230,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget { ...@@ -208,7 +230,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
this.width, this.width,
this.height, this.height,
Curve curve: Curves.linear, Curve curve: Curves.linear,
Duration duration @required Duration duration
}) : super(key: key, curve: curve, duration: duration) { }) : super(key: key, curve: curve, duration: duration) {
assert(decoration == null || decoration.debugAssertValid()); assert(decoration == null || decoration.debugAssertValid());
assert(foregroundDecoration == null || foregroundDecoration.debugAssertValid()); assert(foregroundDecoration == null || foregroundDecoration.debugAssertValid());
...@@ -333,6 +355,14 @@ class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer> ...@@ -333,6 +355,14 @@ class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer>
/// ///
/// Only works if it's the child of a [Stack]. /// Only works if it's the child of a [Stack].
class AnimatedPositioned extends ImplicitlyAnimatedWidget { class AnimatedPositioned extends ImplicitlyAnimatedWidget {
/// Creates a widget that animates its position implicitly.
///
/// Only two out of the three horizontal values ([left], [right],
/// [width]), and only two out of the three vertical values ([top],
/// [bottom], [height]), can be set. In each case, at least one of
/// the three must be null.
///
/// The [curve] and [duration] arguments must not be null.
AnimatedPositioned({ AnimatedPositioned({
Key key, Key key,
this.child, this.child,
...@@ -343,18 +373,21 @@ class AnimatedPositioned extends ImplicitlyAnimatedWidget { ...@@ -343,18 +373,21 @@ class AnimatedPositioned extends ImplicitlyAnimatedWidget {
this.width, this.width,
this.height, this.height,
Curve curve: Curves.linear, Curve curve: Curves.linear,
Duration duration @required Duration duration
}) : super(key: key, curve: curve, duration: duration) { }) : super(key: key, curve: curve, duration: duration) {
assert(left == null || right == null || width == null); assert(left == null || right == null || width == null);
assert(top == null || bottom == null || height == null); assert(top == null || bottom == null || height == null);
} }
/// Creates a widget that animates the rectangle it occupies implicitly.
///
/// The [curve] and [duration] arguments must not be null.
AnimatedPositioned.fromRect({ AnimatedPositioned.fromRect({
Key key, Key key,
this.child, this.child,
Rect rect, Rect rect,
Curve curve: Curves.linear, Curve curve: Curves.linear,
Duration duration @required Duration duration
}) : left = rect.left, }) : left = rect.left,
top = rect.top, top = rect.top,
width = rect.width, width = rect.width,
...@@ -466,12 +499,16 @@ class _AnimatedPositionedState extends AnimatedWidgetBaseState<AnimatedPositione ...@@ -466,12 +499,16 @@ class _AnimatedPositionedState extends AnimatedWidgetBaseState<AnimatedPositione
/// ///
/// Animating an opacity is relatively expensive. /// Animating an opacity is relatively expensive.
class AnimatedOpacity extends ImplicitlyAnimatedWidget { class AnimatedOpacity extends ImplicitlyAnimatedWidget {
/// Creates a widget that animates its opacity implicitly.
///
/// The [opacity] argument must not be null and must be between 0.0 and 1.0,
/// inclusive. The [curve] and [duration] arguments must not be null.
AnimatedOpacity({ AnimatedOpacity({
Key key, Key key,
this.child, this.child,
this.opacity, this.opacity,
Curve curve: Curves.linear, Curve curve: Curves.linear,
Duration duration @required Duration duration
}) : super(key: key, curve: curve, duration: duration) { }) : super(key: key, curve: curve, duration: duration) {
assert(opacity != null && opacity >= 0.0 && opacity <= 1.0); assert(opacity != null && opacity >= 0.0 && opacity <= 1.0);
} }
...@@ -520,12 +557,15 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> { ...@@ -520,12 +557,15 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> {
/// descendant [Text] widgets without explicit style) over a given /// descendant [Text] widgets without explicit style) over a given
/// duration whenever the given style changes. /// duration whenever the given style changes.
class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget { class AnimatedDefaultTextStyle extends ImplicitlyAnimatedWidget {
/// Creates a widget that animates the default text style implicitly.
///
/// The [child], [style], [curve], and [duration] arguments must not be null.
AnimatedDefaultTextStyle({ AnimatedDefaultTextStyle({
Key key, Key key,
this.child, @required this.child,
this.style, @required this.style,
Curve curve: Curves.linear, Curve curve: Curves.linear,
Duration duration @required Duration duration
}) : super(key: key, curve: curve, duration: duration) { }) : super(key: key, curve: curve, duration: duration) {
assert(style != null); assert(style != null);
assert(child != null); assert(child != null);
......
...@@ -6,6 +6,7 @@ import 'debug.dart'; ...@@ -6,6 +6,7 @@ import 'debug.dart';
import 'framework.dart'; import 'framework.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart';
/// The signature of the [LayoutBuilder] builder function. /// The signature of the [LayoutBuilder] builder function.
typedef Widget LayoutWidgetBuilder(BuildContext context, Size size); typedef Widget LayoutWidgetBuilder(BuildContext context, Size size);
...@@ -17,7 +18,13 @@ typedef Widget LayoutWidgetBuilder(BuildContext context, Size size); ...@@ -17,7 +18,13 @@ typedef Widget LayoutWidgetBuilder(BuildContext context, Size size);
/// when the parent constrains the child's size and doesn't depend on the child's /// when the parent constrains the child's size and doesn't depend on the child's
/// intrinsic size. /// intrinsic size.
class LayoutBuilder extends RenderObjectWidget { class LayoutBuilder extends RenderObjectWidget {
LayoutBuilder({ Key key, this.builder }) : super(key: key) { /// Creates a widget that defers its building until layout.
///
/// The [builder] argument must not be null.
LayoutBuilder({
Key key,
@required this.builder
}) : super(key: key) {
assert(builder != null); assert(builder != null);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'clamp_overscrolls.dart'; import 'clamp_overscrolls.dart';
...@@ -133,8 +134,12 @@ class LazyBlockChildren extends LazyBlockDelegate { ...@@ -133,8 +134,12 @@ class LazyBlockChildren extends LazyBlockDelegate {
/// it can use that property to be more efficient. Prefer [ScrollableViewport] /// it can use that property to be more efficient. Prefer [ScrollableViewport]
/// when there is only one child. /// when there is only one child.
class LazyBlock extends StatelessWidget { class LazyBlock extends StatelessWidget {
/// Creates an infinite scrolling list of variable height children.
///
/// The [delegate] argument must not be null.
LazyBlock({ LazyBlock({
Key key, Key key,
@required this.delegate,
this.initialScrollOffset, this.initialScrollOffset,
this.scrollDirection: Axis.vertical, this.scrollDirection: Axis.vertical,
this.onScrollStart, this.onScrollStart,
...@@ -142,9 +147,10 @@ class LazyBlock extends StatelessWidget { ...@@ -142,9 +147,10 @@ class LazyBlock extends StatelessWidget {
this.onScrollEnd, this.onScrollEnd,
this.snapOffsetCallback, this.snapOffsetCallback,
this.scrollableKey, this.scrollableKey,
this.padding, this.padding
this.delegate }) : super(key: key) {
}) : super(key: key); assert(delegate != null);
}
// Warning: keep the dartdoc comments that follow in sync with the copies in // Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, ScrollableGrid, ScrollableViewport, ScrollableList, and // Scrollable, ScrollableGrid, ScrollableViewport, ScrollableList, and
...@@ -276,13 +282,16 @@ typedef void LazyBlockExtentsChangedCallback(double contentExtent, double contai ...@@ -276,13 +282,16 @@ typedef void LazyBlockExtentsChangedCallback(double contentExtent, double contai
/// ///
/// For a scrollable version of this widget, see [LazyBlock]. /// For a scrollable version of this widget, see [LazyBlock].
class LazyBlockViewport extends RenderObjectWidget { class LazyBlockViewport extends RenderObjectWidget {
/// Creates a viewport on an infinite list of variable height children.
///
/// The [delegate] argument must not be null.
LazyBlockViewport({ LazyBlockViewport({
Key key, Key key,
@required this.delegate,
this.startOffset: 0.0, this.startOffset: 0.0,
this.mainAxis: Axis.vertical, this.mainAxis: Axis.vertical,
this.padding, this.padding,
this.onExtentsChanged, this.onExtentsChanged
this.delegate
}) : super(key: key) { }) : super(key: key) {
assert(delegate != null); assert(delegate != null);
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart'; import 'framework.dart';
/// Superclass for locale-specific data provided by the application. /// Superclass for locale-specific data provided by the application.
...@@ -9,10 +11,11 @@ class LocaleQueryData { } // TODO(ianh): We need a better type here. This doesn' ...@@ -9,10 +11,11 @@ class LocaleQueryData { } // TODO(ianh): We need a better type here. This doesn'
/// Establishes a subtree in which locale queries resolve to the given data. /// Establishes a subtree in which locale queries resolve to the given data.
class LocaleQuery extends InheritedWidget { class LocaleQuery extends InheritedWidget {
/// Creates a widget that provides [LocaleQueryData] to its descendants.
LocaleQuery({ LocaleQuery({
Key key, Key key,
this.data, @required this.data,
Widget child @required Widget child
}) : super(key: key, child: child) { }) : super(key: key, child: child) {
assert(child != null); assert(child != null);
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -74,10 +76,13 @@ class MediaQueryData { ...@@ -74,10 +76,13 @@ class MediaQueryData {
/// Establishes a subtree in which media queries resolve to the given data. /// Establishes a subtree in which media queries resolve to the given data.
class MediaQuery extends InheritedWidget { class MediaQuery extends InheritedWidget {
/// Creates a widget that provides [MediaQueryData] to its descendants.
///
/// The [data] and [child] arguments must not be null.
MediaQuery({ MediaQuery({
Key key, Key key,
this.data, @required this.data,
Widget child @required Widget child
}) : super(key: key, child: child) { }) : super(key: key, child: child) {
assert(child != null); assert(child != null);
assert(data != null); assert(data != null);
......
...@@ -124,6 +124,7 @@ class MimicOverlayEntry { ...@@ -124,6 +124,7 @@ class MimicOverlayEntry {
/// A widget that copies the appearance of another widget. /// A widget that copies the appearance of another widget.
class Mimic extends StatelessWidget { class Mimic extends StatelessWidget {
/// Creates a widget that copies the appearance of another widget.
Mimic({ Key key, this.original }) : super(key: key); Mimic({ Key key, this.original }) : super(key: key);
/// A handle to the widget that this widget should copy. /// A handle to the widget that this widget should copy.
...@@ -142,6 +143,7 @@ class Mimic extends StatelessWidget { ...@@ -142,6 +143,7 @@ class Mimic extends StatelessWidget {
/// This widget's State, [MimicableState], contains an API for initiating the /// This widget's State, [MimicableState], contains an API for initiating the
/// mimic operation. /// mimic operation.
class Mimicable extends StatefulWidget { class Mimicable extends StatefulWidget {
/// Creates a widget that can be copies by a [Mimic].
Mimicable({ Key key, this.child }) : super(key: key); Mimicable({ Key key, this.child }) : super(key: key);
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
......
...@@ -8,8 +8,9 @@ import 'gesture_detector.dart'; ...@@ -8,8 +8,9 @@ import 'gesture_detector.dart';
import 'navigator.dart'; import 'navigator.dart';
import 'transitions.dart'; import 'transitions.dart';
/// Prevents the user from interacting with widgets behind itself. /// A widget that prevents the user from interacting with widgets behind itself.
class ModalBarrier extends StatelessWidget { class ModalBarrier extends StatelessWidget {
/// Creates a widget that blocks user interaction.
ModalBarrier({ ModalBarrier({
Key key, Key key,
this.color, this.color,
...@@ -45,8 +46,9 @@ class ModalBarrier extends StatelessWidget { ...@@ -45,8 +46,9 @@ class ModalBarrier extends StatelessWidget {
} }
} }
/// Prevents the user from interacting with widgets behind itself. /// A widget that prevents the user from interacting with widgets behind itself.
class AnimatedModalBarrier extends AnimatedWidget { class AnimatedModalBarrier extends AnimatedWidget {
/// Creates a widget that blocks user interaction.
AnimatedModalBarrier({ AnimatedModalBarrier({
Key key, Key key,
Animation<Color> color, Animation<Color> color,
...@@ -62,7 +64,7 @@ class AnimatedModalBarrier extends AnimatedWidget { ...@@ -62,7 +64,7 @@ class AnimatedModalBarrier extends AnimatedWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new ModalBarrier( return new ModalBarrier(
color: color.value, color: color?.value,
dismissable: dismissable dismissable: dismissable
); );
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart'; import 'framework.dart';
import 'overlay.dart'; import 'overlay.dart';
...@@ -79,6 +81,7 @@ abstract class Route<T> { ...@@ -79,6 +81,7 @@ abstract class Route<T> {
/// Data that might be useful in constructing a [Route]. /// Data that might be useful in constructing a [Route].
class RouteSettings { class RouteSettings {
/// Creates data used to construct routes.
const RouteSettings({ const RouteSettings({
this.name, this.name,
this.mostValuableKeys, this.mostValuableKeys,
...@@ -86,6 +89,8 @@ class RouteSettings { ...@@ -86,6 +89,8 @@ class RouteSettings {
}); });
/// The name of the route (e.g., "/settings"). /// The name of the route (e.g., "/settings").
///
/// If null, the route is anonymous.
final String name; final String name;
/// The set of keys that are most relevant for constructoring [Hero] /// The set of keys that are most relevant for constructoring [Hero]
...@@ -132,7 +137,7 @@ class NavigatorObserver { ...@@ -132,7 +137,7 @@ class NavigatorObserver {
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { } void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { }
} }
/// Manages a set of child widgets with a stack discipline. /// A widget that manages a set of child widgets with a stack discipline.
/// ///
/// Many apps have a navigator near the top of their widget hierarchy in order /// Many apps have a navigator near the top of their widget hierarchy in order
/// to display their logical history using an [Overlay] with the most recently /// to display their logical history using an [Overlay] with the most recently
...@@ -141,10 +146,13 @@ class NavigatorObserver { ...@@ -141,10 +146,13 @@ class NavigatorObserver {
/// around in the overlay. Similarly, the navigator can be used to show a dialog /// around in the overlay. Similarly, the navigator can be used to show a dialog
/// by positioning the dialog widget above the current page. /// by positioning the dialog widget above the current page.
class Navigator extends StatefulWidget { class Navigator extends StatefulWidget {
/// Creates a widget that maintains a stack-based history of child widgets.
///
/// The [onGenerateRoute] argument must not be null.
Navigator({ Navigator({
Key key, Key key,
this.initialRoute, this.initialRoute,
this.onGenerateRoute, @required this.onGenerateRoute,
this.onUnknownRoute, this.onUnknownRoute,
this.observer this.observer
}) : super(key: key) { }) : super(key: key) {
......
...@@ -24,8 +24,9 @@ abstract class Notification { ...@@ -24,8 +24,9 @@ abstract class Notification {
} }
} }
/// Listens for [Notification]s bubbling up the tree. /// A widget that listens for [Notification]s bubbling up the tree.
class NotificationListener<T extends Notification> extends StatelessWidget { class NotificationListener<T extends Notification> extends StatelessWidget {
/// Creates a widget that listens for notifications.
NotificationListener({ NotificationListener({
Key key, Key key,
this.child, this.child,
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -42,7 +44,7 @@ class OverlayEntry { ...@@ -42,7 +44,7 @@ class OverlayEntry {
/// [Overlay.of] and then call [OverlayState.insert]. To remove the entry, /// [Overlay.of] and then call [OverlayState.insert]. To remove the entry,
/// call [remove] on the overlay entry itself. /// call [remove] on the overlay entry itself.
OverlayEntry({ OverlayEntry({
this.builder, @required this.builder,
bool opaque: false bool opaque: false
}) : _opaque = opaque { }) : _opaque = opaque {
assert(builder != null); assert(builder != null);
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart'; import 'framework.dart';
class _StorageEntryIdentifier { class _StorageEntryIdentifier {
...@@ -88,13 +90,18 @@ class PageStorageBucket { ...@@ -88,13 +90,18 @@ class PageStorageBucket {
} }
} }
/// Establishes a page storage bucket for this widget subtree. /// A widget that establishes a page storage bucket for this widget subtree.
class PageStorage extends StatelessWidget { class PageStorage extends StatelessWidget {
/// Creates a widget that provides a storage bucket for its descendants.
///
/// The [bucket] argument must not be null.
PageStorage({ PageStorage({
Key key, Key key,
this.child, @required this.bucket,
this.bucket this.child
}) : super(key: key); }) : super(key: key) {
assert(bucket != null);
}
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
final Widget child; final Widget child;
......
...@@ -14,12 +14,39 @@ import 'virtual_viewport.dart'; ...@@ -14,12 +14,39 @@ import 'virtual_viewport.dart';
/// Controls how a pageable list should behave during a fling. /// Controls how a pageable list should behave during a fling.
enum PageableListFlingBehavior { enum PageableListFlingBehavior {
/// A fling gesture can scroll the list by more than one page.
canFlingAcrossMultiplePages, canFlingAcrossMultiplePages,
/// A fling gesture can scroll the list by at most one page.
stopAtNextPage stopAtNextPage
} }
abstract class PageableListBase extends Scrollable { /// A base class for widgets that display one page at a time.
PageableListBase({ ///
/// [Pageable] widgets are similar to [Scrollable] except that they display a
/// single child at a time. When being scrolled, they can display adjacent
/// pages, but when the user stops scrolling, they settle their scroll offset to
/// a value that shows a single page.
///
/// [Pageable] uses different units for its scroll offset than [Scrollable]. One
/// unit of scroll offset cooresponds to one child widget, which means a scroll
/// offset of 2.75 indicates that the viewport is three quarters of the way
/// between the child with index 2 and the child with index 3.
///
/// Widgets that subclass [Pageable] typically use state objects that subclass
/// [PageableState].
///
/// See also:
///
/// * [PageableList], which pages through an iterable list of children.
/// * [PageableLazyList], which pages through a lazily constructed list of
/// children.
abstract class Pageable extends Scrollable {
/// Initializes fields for subclasses.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
Pageable({
Key key, Key key,
double initialScrollOffset, double initialScrollOffset,
Axis scrollDirection: Axis.vertical, Axis scrollDirection: Axis.vertical,
...@@ -64,11 +91,21 @@ abstract class PageableListBase extends Scrollable { ...@@ -64,11 +91,21 @@ abstract class PageableListBase extends Scrollable {
int get _itemCount; int get _itemCount;
} }
/// Scrollable widget that scrolls one "page" at a time. /// A widget that pages through an iterable list of children.
/// ///
/// In a pageable list, one child is visible at a time. Scrolling the list /// A [PageableList] displays a single child at a time. When being scrolled, it
/// reveals either the next or previous child. /// can display adjacent pages, but when the user stops scrolling, it settles
class PageableList extends PageableListBase { /// its scroll offset to a value that shows a single page.
///
/// See also:
///
/// * [PageableLazyList], which pages through a lazily constructed list of
/// children.
class PageableList extends Pageable {
/// Creates a widget that pages through an iterable list of children.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
PageableList({ PageableList({
Key key, Key key,
double initialScrollOffset, double initialScrollOffset,
...@@ -110,7 +147,20 @@ class PageableList extends PageableListBase { ...@@ -110,7 +147,20 @@ class PageableList extends PageableListBase {
PageableListState<PageableList> createState() => new PageableListState<PageableList>(); PageableListState<PageableList> createState() => new PageableListState<PageableList>();
} }
class PageableLazyList extends PageableListBase { /// A widget that pages through a lazily constructed list of children.
///
/// A [PageableList] displays a single child at a time. When being scrolled, it
/// can display adjacent pages, but when the user stops scrolling, it settles
/// its scroll offset to a value that shows a single page.
///
/// See also:
///
/// * [PageableList], which pages through an iterable list of children.
class PageableLazyList extends Pageable {
/// Creates a widget that pages through a lazily constructed list of children.
///
/// The [scrollDirection], [scrollAnchor], and [itemsSnapAlignment] arguments
/// must not be null.
PageableLazyList({ PageableLazyList({
Key key, Key key,
double initialScrollOffset, double initialScrollOffset,
...@@ -155,7 +205,12 @@ class PageableLazyList extends PageableListBase { ...@@ -155,7 +205,12 @@ class PageableLazyList extends PageableListBase {
_PageableLazyListState createState() => new _PageableLazyListState(); _PageableLazyListState createState() => new _PageableLazyListState();
} }
abstract class _PageableListStateBase<T extends PageableListBase> extends ScrollableState<T> { /// State for widgets that subclass [Pageable].
///
/// Specializes [ScrollableState] to support page-based scrolling.
///
/// Subclasses typically override [buildContent] to build viewports.
abstract class PageableState<T extends Pageable> extends ScrollableState<T> {
int get _itemCount => config._itemCount; int get _itemCount => config._itemCount;
int _previousItemCount; int _previousItemCount;
...@@ -202,7 +257,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll ...@@ -202,7 +257,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll
} }
@override @override
void didUpdateConfig(PageableListBase oldConfig) { void didUpdateConfig(Pageable oldConfig) {
super.didUpdateConfig(oldConfig); super.didUpdateConfig(oldConfig);
bool scrollBehaviorUpdateNeeded = config.scrollDirection != oldConfig.scrollDirection; bool scrollBehaviorUpdateNeeded = config.scrollDirection != oldConfig.scrollDirection;
...@@ -287,7 +342,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll ...@@ -287,7 +342,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll
/// ///
/// Widgets that subclass [PageableList] can subclass this class to have /// Widgets that subclass [PageableList] can subclass this class to have
/// sensible default behaviors for pageable lists. /// sensible default behaviors for pageable lists.
class PageableListState<T extends PageableList> extends _PageableListStateBase<T> { class PageableListState<T extends PageableList> extends PageableState<T> {
@override @override
Widget buildContent(BuildContext context) { Widget buildContent(BuildContext context) {
return new PageViewport( return new PageViewport(
...@@ -300,7 +355,7 @@ class PageableListState<T extends PageableList> extends _PageableListStateBase<T ...@@ -300,7 +355,7 @@ class PageableListState<T extends PageableList> extends _PageableListStateBase<T
} }
} }
class _PageableLazyListState extends _PageableListStateBase<PageableLazyList> { class _PageableLazyListState extends PageableState<PageableLazyList> {
@override @override
Widget buildContent(BuildContext context) { Widget buildContent(BuildContext context) {
return new LazyPageViewport( return new LazyPageViewport(
...@@ -321,13 +376,37 @@ class _VirtualPageViewport extends VirtualViewport { ...@@ -321,13 +376,37 @@ class _VirtualPageViewport extends VirtualViewport {
this.itemsWrap this.itemsWrap
) { ) {
assert(mainAxis != null); assert(mainAxis != null);
assert(anchor != null);
} }
@override @override
final double startOffset; final double startOffset;
/// The axis along which the viewport is bigger on the inside than the outside.
final Axis mainAxis; final Axis mainAxis;
/// Whether to place first child at the start of the container or the last
/// child at the end of the container, when the viewport has not been offset.
///
/// For example, if the [mainAxis] is [Axis.vertical] and
/// there are enough items to overflow the container, then
/// [ViewportAnchor.start] means that the top of the first item
/// should be aligned with the top of the viewport with the last
/// item below the bottom, and [ViewportAnchor.end] means the bottom
/// of the last item should be aligned with the bottom of the
/// viewport, with the first item above the top.
///
/// This also affects whether, when an item is added or removed, the
/// displacement will be towards the first item or the last item.
/// Continuing the earlier example, if a new item is inserted in the
/// middle of the list, in the [ViewportAnchor.start] case the items
/// after it (with greater indices, down to the item with the
/// highest index) will be pushed down, while in the
/// [ViewportAnchor.end] case the items before it (with lower
/// indices, up to the item with the index 0) will be pushed up.
final ViewportAnchor anchor; final ViewportAnchor anchor;
/// Whether the first item should be revealed after scrolling past the last item.
final bool itemsWrap; final bool itemsWrap;
@override @override
...@@ -433,7 +512,21 @@ class _VirtualPageViewportElement extends VirtualViewportElement { ...@@ -433,7 +512,21 @@ class _VirtualPageViewportElement extends VirtualViewportElement {
} }
} }
/// A virtual viewport that displays a single child at a time.
///
/// Useful for [Pageable] widgets.
///
/// One unit of start offset cooresponds to one child widget, which means a
/// start offset of 2.75 indicates that the viewport is three quarters of the
/// way between the child with index 2 and the child with index 3.
///
/// [PageViewport] differs from [LazyPageViewport] in that [PageViewport] uses
/// an [Iterable] list of children. That makes [PageViewport] suitable for a
/// large (but not extremely large or infinite) list of children.
class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable { class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable {
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
PageViewport({ PageViewport({
double startOffset: 0.0, double startOffset: 0.0,
Axis mainAxis: Axis.vertical, Axis mainAxis: Axis.vertical,
...@@ -451,7 +544,22 @@ class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable ...@@ -451,7 +544,22 @@ class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable
final Iterable<Widget> children; final Iterable<Widget> children;
} }
/// A virtual viewport that displays a single child at a time.
///
/// Useful for [Pageable] widgets.
///
/// One unit of start offset cooresponds to one child widget, which means a
/// start offset of 2.75 indicates that the viewport is three quarters of the
/// way between the child with index 2 and the child with index 3.
///
/// [LazyPageViewport] differs from [PageViewport] in that [LazyPageViewport]
/// uses an [ItemListBuilder] to lazily create children. That makes
/// [LazyPageViewport] suitable for an extremely large or infinite list of
/// children but alos makes it more verbose than [PageViewport].
class LazyPageViewport extends _VirtualPageViewport with VirtualViewportFromBuilder { class LazyPageViewport extends _VirtualPageViewport with VirtualViewportFromBuilder {
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
LazyPageViewport({ LazyPageViewport({
double startOffset: 0.0, double startOffset: 0.0,
Axis mainAxis: Axis.vertical, Axis mainAxis: Axis.vertical,
......
...@@ -11,6 +11,7 @@ import 'routes.dart'; ...@@ -11,6 +11,7 @@ import 'routes.dart';
/// A modal route that replaces the entire screen. /// A modal route that replaces the entire screen.
abstract class PageRoute<T> extends ModalRoute<T> { abstract class PageRoute<T> extends ModalRoute<T> {
/// Creates a modal route that replaces the entire screen.
PageRoute({ PageRoute({
Completer<T> completer, Completer<T> completer,
RouteSettings settings: const RouteSettings() RouteSettings settings: const RouteSettings()
......
...@@ -27,7 +27,11 @@ class PerformanceOverlay extends LeafRenderObjectWidget { ...@@ -27,7 +27,11 @@ class PerformanceOverlay extends LeafRenderObjectWidget {
/// Create a performance overlay that only displays specific statistics. The /// Create a performance overlay that only displays specific statistics. The
/// mask is created by shifting 1 by the index of the specific /// mask is created by shifting 1 by the index of the specific
/// [StatisticOption] to enable. /// [StatisticOption] to enable.
PerformanceOverlay({ this.optionsMask, this.rasterizerThreshold: 0, Key key }) : super(key: key); PerformanceOverlay({
Key key,
this.optionsMask,
this.rasterizerThreshold: 0
}) : super(key: key);
/// Create a performance overlay that displays all available statistics /// Create a performance overlay that displays all available statistics
PerformanceOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 }) PerformanceOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 })
......
...@@ -7,6 +7,7 @@ import 'framework.dart'; ...@@ -7,6 +7,7 @@ import 'framework.dart';
/// A widget whose child can be mutated. /// A widget whose child can be mutated.
class Placeholder extends StatefulWidget { class Placeholder extends StatefulWidget {
/// Creates a widget whose child can be mutated.
Placeholder({ Key key }) : super(key: key); Placeholder({ Key key }) : super(key: key);
@override @override
......
...@@ -9,7 +9,24 @@ import 'package:sky_services/sky/input_event.mojom.dart' as mojom; ...@@ -9,7 +9,24 @@ import 'package:sky_services/sky/input_event.mojom.dart' as mojom;
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
/// A widget that calls a callback whenever the user presses a key on a keyboard.
///
/// A [RawKeyboardListener] is useful for listening to raw key events and
/// hardware buttons that are represented as keys. Typically used by games and
/// other apps that use keyboards for purposes other than text entry.
///
/// For text entry, consider using a [RawInputLine], which integrates with
/// on-screen keyboards and input method editors (IMEs).
///
/// See also:
///
/// * [RawInputLine], which should be used instead of this widget for text
/// entry.
class RawKeyboardListener extends StatefulWidget { class RawKeyboardListener extends StatefulWidget {
/// Creates a widget that receives raw keyboard events.
///
/// For text entry, consider using a [RawInputLine], which integrates with
/// on-screen keyboards and input method editors (IMEs).
RawKeyboardListener({ RawKeyboardListener({
Key key, Key key,
this.focused: false, this.focused: false,
...@@ -19,8 +36,13 @@ class RawKeyboardListener extends StatefulWidget { ...@@ -19,8 +36,13 @@ class RawKeyboardListener extends StatefulWidget {
assert(child != null); assert(child != null);
} }
/// Whether this widget should actually listen for raw keyboard events.
///
/// Typically set to the value returned by [Focus.at] for the [GlobalKey] of
/// the widget that builds the raw keyboard listener.
final bool focused; final bool focused;
/// Called whenever this widget receives a raw keyboard event.
final ValueChanged<mojom.InputEvent> onKey; final ValueChanged<mojom.InputEvent> onKey;
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
......
...@@ -69,6 +69,7 @@ abstract class OverlayRoute<T> extends Route<T> { ...@@ -69,6 +69,7 @@ abstract class OverlayRoute<T> extends Route<T> {
/// A route with entrance and exit transitions. /// A route with entrance and exit transitions.
abstract class TransitionRoute<T> extends OverlayRoute<T> { abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// Creates a route with entrance and exit transitions.
TransitionRoute({ TransitionRoute({
Completer<T> popCompleter, Completer<T> popCompleter,
Completer<T> transitionCompleter Completer<T> transitionCompleter
...@@ -146,6 +147,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -146,6 +147,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
} }
} }
/// The animation for the route being pushed on top of this route. This
/// animation lets this route coordinate with the entrance and exit transition
/// of routes pushed on top of this route.
Animation<double> get forwardAnimation => _forwardAnimation; Animation<double> get forwardAnimation => _forwardAnimation;
final ProxyAnimation _forwardAnimation = new ProxyAnimation(kAlwaysDismissedAnimation); final ProxyAnimation _forwardAnimation = new ProxyAnimation(kAlwaysDismissedAnimation);
...@@ -246,6 +250,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -246,6 +250,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
super.dispose(); super.dispose();
} }
/// A short description of this route useful for debugging.
String get debugLabel => '$runtimeType'; String get debugLabel => '$runtimeType';
@override @override
...@@ -254,6 +259,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -254,6 +259,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// An entry in the history of a [LocalHistoryRoute]. /// An entry in the history of a [LocalHistoryRoute].
class LocalHistoryEntry { class LocalHistoryEntry {
/// Creates an entry in the history of a [LocalHistoryRoute].
LocalHistoryEntry({ this.onRemove }); LocalHistoryEntry({ this.onRemove });
/// Called when this entry is removed from the history of its associated [LocalHistoryRoute]. /// Called when this entry is removed from the history of its associated [LocalHistoryRoute].
...@@ -439,6 +445,7 @@ class _ModalScopeState extends State<_ModalScope> { ...@@ -439,6 +445,7 @@ class _ModalScopeState extends State<_ModalScope> {
/// however; for example, a pop-up menu uses a ModalRoute but only shows the menu /// however; for example, a pop-up menu uses a ModalRoute but only shows the menu
/// in a small box overlapping the previous route. /// in a small box overlapping the previous route.
abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T> { abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T> {
/// Creates a route that blocks interaction with previous routes.
ModalRoute({ ModalRoute({
Completer<T> completer, Completer<T> completer,
this.settings: const RouteSettings() this.settings: const RouteSettings()
...@@ -582,6 +589,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -582,6 +589,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// A modal route that overlays a widget over the current route. /// A modal route that overlays a widget over the current route.
abstract class PopupRoute<T> extends ModalRoute<T> { abstract class PopupRoute<T> extends ModalRoute<T> {
/// Creates a modal route that overlays a widget over the current route.
PopupRoute({ Completer<T> completer }) : super(completer: completer); PopupRoute({ Completer<T> completer }) : super(completer: completer);
@override @override
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/physics.dart'; import 'package:flutter/physics.dart';
import 'package:meta/meta.dart';
const double _kSecondsPerMillisecond = 1000.0; const double _kSecondsPerMillisecond = 1000.0;
const double _kScrollDrag = 0.025; const double _kScrollDrag = 0.025;
...@@ -47,6 +48,12 @@ abstract class ScrollBehavior<T, U> { ...@@ -47,6 +48,12 @@ abstract class ScrollBehavior<T, U> {
debugFillDescription(description); debugFillDescription(description);
return '$runtimeType(${description.join("; ")})'; return '$runtimeType(${description.join("; ")})';
} }
/// Accumulates a list of strings describing the current node's fields, one
/// field per string. Subclasses should override this to have their
/// information included in [toString].
@protected
@mustCallSuper
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
description.add(isScrollable ? 'scrollable' : 'not scrollable'); description.add(isScrollable ? 'scrollable' : 'not scrollable');
} }
...@@ -55,6 +62,7 @@ abstract class ScrollBehavior<T, U> { ...@@ -55,6 +62,7 @@ abstract class ScrollBehavior<T, U> {
/// A scroll behavior for a scrollable widget with linear extent (i.e. /// A scroll behavior for a scrollable widget with linear extent (i.e.
/// that only scrolls along one axis). /// that only scrolls along one axis).
abstract class ExtentScrollBehavior extends ScrollBehavior<double, double> { abstract class ExtentScrollBehavior extends ScrollBehavior<double, double> {
/// Creates a scroll behavior for a scrollable widget with linear extent.
ExtentScrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) ExtentScrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 })
: _contentExtent = contentExtent, _containerExtent = containerExtent; : _contentExtent = contentExtent, _containerExtent = containerExtent;
...@@ -102,6 +110,7 @@ abstract class ExtentScrollBehavior extends ScrollBehavior<double, double> { ...@@ -102,6 +110,7 @@ abstract class ExtentScrollBehavior extends ScrollBehavior<double, double> {
/// A scroll behavior that prevents the user from exceeding scroll bounds. /// A scroll behavior that prevents the user from exceeding scroll bounds.
class BoundedBehavior extends ExtentScrollBehavior { class BoundedBehavior extends ExtentScrollBehavior {
/// Creates a scroll behavior that does not overscroll.
BoundedBehavior({ BoundedBehavior({
double contentExtent: 0.0, double contentExtent: 0.0,
double containerExtent: 0.0, double containerExtent: 0.0,
...@@ -154,6 +163,7 @@ Simulation _createSnapScrollSimulation(double startOffset, double endOffset, dou ...@@ -154,6 +163,7 @@ Simulation _createSnapScrollSimulation(double startOffset, double endOffset, dou
/// A scroll behavior that does not prevent the user from exeeding scroll bounds. /// A scroll behavior that does not prevent the user from exeeding scroll bounds.
class UnboundedBehavior extends ExtentScrollBehavior { class UnboundedBehavior extends ExtentScrollBehavior {
/// Creates a scroll behavior with no scrolling limits.
UnboundedBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 }) UnboundedBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 })
: super(contentExtent: contentExtent, containerExtent: containerExtent); : super(contentExtent: contentExtent, containerExtent: containerExtent);
...@@ -184,6 +194,7 @@ class UnboundedBehavior extends ExtentScrollBehavior { ...@@ -184,6 +194,7 @@ class UnboundedBehavior extends ExtentScrollBehavior {
/// A scroll behavior that lets the user scroll beyond the scroll bounds with some resistance. /// A scroll behavior that lets the user scroll beyond the scroll bounds with some resistance.
class OverscrollBehavior extends BoundedBehavior { class OverscrollBehavior extends BoundedBehavior {
/// Creates a scroll behavior that resists, but does not prevent, scrolling beyond its limits.
OverscrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0, double minScrollOffset: 0.0 }) OverscrollBehavior({ double contentExtent: 0.0, double containerExtent: 0.0, double minScrollOffset: 0.0 })
: super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset); : super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset);
...@@ -217,6 +228,7 @@ class OverscrollBehavior extends BoundedBehavior { ...@@ -217,6 +228,7 @@ class OverscrollBehavior extends BoundedBehavior {
/// A scroll behavior that lets the user scroll beyond the scroll bounds only when the bounds are disjoint. /// A scroll behavior that lets the user scroll beyond the scroll bounds only when the bounds are disjoint.
class OverscrollWhenScrollableBehavior extends OverscrollBehavior { class OverscrollWhenScrollableBehavior extends OverscrollBehavior {
/// Creates a scroll behavior that allows overscrolling only when some amount of scrolling is already possible.
OverscrollWhenScrollableBehavior({ double contentExtent: 0.0, double containerExtent: 0.0, double minScrollOffset: 0.0 }) OverscrollWhenScrollableBehavior({ double contentExtent: 0.0, double containerExtent: 0.0, double minScrollOffset: 0.0 })
: super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset); : super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset);
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
import 'framework.dart'; import 'framework.dart';
import 'scroll_behavior.dart'; import 'scroll_behavior.dart';
/// Controls how [Scrollable] widgets in a subtree behave.
///
/// Used by [ScrollConfiguration].
class ScrollConfigurationDelegate { class ScrollConfigurationDelegate {
/// Creates a delegate with sensible default behaviors.
const ScrollConfigurationDelegate();
/// Returns the ScrollBehavior to be used by generic scrolling containers like /// Returns the ScrollBehavior to be used by generic scrolling containers like
/// [Block]. Returns a new [OverscrollWhenScrollableBehavior] by default. /// [Block]. Returns a new [OverscrollWhenScrollableBehavior] by default.
ExtentScrollBehavior createScrollBehavior() => new OverscrollWhenScrollableBehavior(); ExtentScrollBehavior createScrollBehavior() => new OverscrollWhenScrollableBehavior();
...@@ -22,14 +28,13 @@ class ScrollConfigurationDelegate { ...@@ -22,14 +28,13 @@ class ScrollConfigurationDelegate {
bool updateShouldNotify(ScrollConfigurationDelegate old) => false; bool updateShouldNotify(ScrollConfigurationDelegate old) => false;
} }
/// Used by descendants to initialize and wrap the [Scrollable] widgets /// A widget that controls descendant [Scrollable] widgets.
/// they create.
/// ///
/// Classes that create Scrollables are not required to depend on this /// Classes that create Scrollables are not required to depend on this
/// Widget. The following general purpose scrolling widgets do depend /// Widget. The following general purpose scrolling widgets do depend
/// on ScrollConfiguration: Block, LazyBlock, ScrollableViewport, /// on [ScrollConfiguration]: [Block], [LazyBlock], [ScrollableViewport],
/// ScrollableList, ScrollableLazyList. The Scrollable base class uses /// [ScrollableList], [ScrollableLazyList]. The [Scrollable] base class uses
/// ScrollConfiguration to create its [ScrollBehavior]. /// [ScrollConfiguration] to create its [ScrollBehavior].
class ScrollConfiguration extends InheritedWidget { class ScrollConfiguration extends InheritedWidget {
ScrollConfiguration({ ScrollConfiguration({
Key key, Key key,
...@@ -37,7 +42,7 @@ class ScrollConfiguration extends InheritedWidget { ...@@ -37,7 +42,7 @@ class ScrollConfiguration extends InheritedWidget {
Widget child Widget child
}) : super(key: key, child: child); }) : super(key: key, child: child);
static final ScrollConfigurationDelegate _defaultDelegate = new ScrollConfigurationDelegate(); static final ScrollConfigurationDelegate _defaultDelegate = const ScrollConfigurationDelegate();
/// Defines the ScrollBehavior and scrollable wrapper for descendants. /// Defines the ScrollBehavior and scrollable wrapper for descendants.
final ScrollConfigurationDelegate delegate; final ScrollConfigurationDelegate delegate;
......
...@@ -38,6 +38,9 @@ typedef double SnapOffsetCallback(double scrollOffset, Size containerSize); ...@@ -38,6 +38,9 @@ typedef double SnapOffsetCallback(double scrollOffset, Size containerSize);
/// Widgets that subclass [Scrollable] typically use state objects that subclass /// Widgets that subclass [Scrollable] typically use state objects that subclass
/// [ScrollableState]. /// [ScrollableState].
class Scrollable extends StatefulWidget { class Scrollable extends StatefulWidget {
/// Initializes fields for subclasses.
///
/// The [scrollDirection] and [scrollAnchor] arguments must not be null.
Scrollable({ Scrollable({
Key key, Key key,
this.initialScrollOffset, this.initialScrollOffset,
......
...@@ -274,6 +274,9 @@ class FadeTransition extends AnimatedWidget { ...@@ -274,6 +274,9 @@ class FadeTransition extends AnimatedWidget {
/// appropriate for rectangles that are described in terms of offsets from /// appropriate for rectangles that are described in terms of offsets from
/// other rectangles. /// other rectangles.
class RelativeRectTween extends Tween<RelativeRect> { class RelativeRectTween extends Tween<RelativeRect> {
/// Creates a relative rect tween.
///
/// The [begin] and [end] arguments must not be null.
RelativeRectTween({ RelativeRect begin, RelativeRect end }) RelativeRectTween({ RelativeRect begin, RelativeRect end })
: super(begin: begin, end: end); : super(begin: begin, end: end);
......
...@@ -2,11 +2,19 @@ ...@@ -2,11 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart'; import 'framework.dart';
/// A widget that has exactly one inflated instance in the tree. /// A widget that has exactly one inflated instance in the tree.
abstract class UniqueWidget<T extends State> extends StatefulWidget { abstract class UniqueWidget<T extends State> extends StatefulWidget {
UniqueWidget({ GlobalKey key }) : super(key: key) { /// Creates a widget that has exactly one inflated instance in the tree.
///
/// The [key] argument cannot be null because it identifies the unique
/// inflated instance of this widget.
UniqueWidget({
@required GlobalKey key
}) : super(key: key) {
assert(key != null); assert(key != null);
} }
...@@ -14,6 +22,8 @@ abstract class UniqueWidget<T extends State> extends StatefulWidget { ...@@ -14,6 +22,8 @@ abstract class UniqueWidget<T extends State> extends StatefulWidget {
T createState(); T createState();
/// The state for the unique inflated instance of this widget. /// The state for the unique inflated instance of this widget.
///
/// Might be null if the widget is not currently in the tree.
T get currentState { T get currentState {
GlobalKey globalKey = key; GlobalKey globalKey = key;
return globalKey.currentState; return globalKey.currentState;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment