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 {
/// This description is often somewhat long.
///
/// 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() {
RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = null;
......@@ -2105,9 +2105,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
return result.toString();
}
/// Returns a list of strings describing the current node's fields, one field
/// per string. Subclasses should override this to have their information
/// included in toStringDeep().
/// 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 [toStringDeep].
@protected
void debugFillDescription(List<String> description) {
if (debugCreator != null)
......
......@@ -40,6 +40,8 @@ ActivityProxy _initActivityProxy() {
}
final ActivityProxy _activityProxy = _initActivityProxy();
/// A singleton for interacting with the current Android activity.
final Activity activity = _activityProxy;
Color _cachedPrimaryColor;
......
......@@ -15,7 +15,9 @@ mojom.ApplicationMessagesProxy _initHostAppMessagesProxy() {
final mojom.ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy();
/// Signature for receiving [HostMessages].
typedef Future<String> HostMessageCallback(String message);
typedef Object _SendStringResponseFactory(String response);
class _ApplicationMessagesImpl extends mojom.ApplicationMessages {
......
......@@ -23,10 +23,14 @@ class Clipboard {
Clipboard._();
/// Stores the given clipboard data on the clipboard.
static void setClipboardData(mojom.ClipboardData 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 {
return (await _clipboardProxy.getClipboardData(format)).clip;
}
......
......@@ -8,6 +8,11 @@ import 'dart:ui' as ui show Image, decodeImageFromDataPipe, decodeImageFromList;
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) {
Completer<ui.Image> completer = new Completer<ui.Image>();
ui.decodeImageFromDataPipe(consumerHandle.handle.h, (ui.Image image) {
......@@ -16,6 +21,11 @@ Future<ui.Image> decodeImageFromDataPipe(MojoDataPipeConsumer consumerHandle) {
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) {
Completer<ui.Image> completer = new Completer<ui.Image>();
ui.decodeImageFromList(list, (ui.Image image) {
......
......@@ -57,6 +57,11 @@ typedef void ImageListener(ImageInfo image);
/// ImageResource objects can also represent an image that hasn't finished
/// loading.
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) {
_futureImage.then(
_handleImageLoaded,
......
......@@ -14,17 +14,28 @@ export 'package:sky_services/editing/editing.mojom.dart' show KeyboardType;
///
/// Most clients will want to use the [keyboard] singleton instance.
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);
// The service is exposed in case you need direct access.
// However, as a general rule, you should be able to do
// most of what you need using only this class.
/// The underlying keyboard service.
///
/// 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;
KeyboardHandle _currentHandle;
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) {
assert(stub != null);
_currentHandle?.release();
......@@ -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 {
KeyboardHandle._(Keyboard keyboard) : _keyboard = keyboard, _attached = true;
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 _attached;
/// Request that the keyboard become visible (if necesssary).
void show() {
assert(_attached);
assert(_keyboard._currentHandle == this);
_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() {
if (_attached) {
assert(_keyboard._currentHandle == this);
......@@ -75,6 +101,19 @@ class KeyboardHandle {
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) {
assert(_attached);
assert(_keyboard._currentHandle == this);
......@@ -87,4 +126,9 @@ mojom.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);
......@@ -255,12 +255,18 @@ void debugDumpApp() {
debugPrint(WidgetsBinding.instance.renderViewElement.toStringDeep());
}
/// This class provides a bridge from a RenderObject to an Element tree. The
/// given container is the RenderObject that the Element tree should be inserted
/// into. It must be a RenderObject that implements the
/// RenderObjectWithChildMixin protocol. The type argument T is the kind of
/// RenderObject that the container expects as its child.
/// A bridge from a [RenderObject] to an [Element] tree.
///
/// The given container is the [RenderObject] that the [Element] tree should be
/// inserted into. It must be a [RenderObject] that implements the
/// [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 {
/// Creates a bridge from a [RenderObject] to an [Element] tree.
///
/// Used by [WidgetsBinding] to attach the root widget to the [RenderView].
RenderObjectToWidgetAdapter({
this.child,
RenderObjectWithChildMixin<T> container,
......@@ -270,8 +276,10 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
/// The widget below this widget in the tree.
final Widget child;
/// The [RenderObject] that is the parent of the [Element] created by this widget.
final RenderObjectWithChildMixin<T> container;
/// A short description of this widget used by debugging aids.
final String debugShortDescription;
@override
......@@ -283,6 +291,12 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
@override
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]) {
owner.lockState(() {
if (element == null) {
......@@ -300,15 +314,22 @@ class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWi
String toStringShort() => debugShortDescription ?? super.toStringShort();
}
/// This element class is the instantiation of a [RenderObjectToWidgetAdapter].
/// 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).
/// A [RootRenderObjectElement] that is hosted by a [RenderObject].
///
/// 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
/// whose container is the RenderView that connects to the Flutter engine. In
/// In typical usage, it will be instantiated for a [RenderObjectToWidgetAdapter]
/// whose container is the [RenderView] that connects to the Flutter engine. In
/// 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 {
/// 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);
@override
......
......@@ -9,9 +9,15 @@ import 'media_query.dart';
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 {
/// Creates a widget that is replaced by content from another process.
ChildView({ Key key, this.child }) : super(key: key);
/// A connection to the child whose content will replace this widget.
final ChildViewConnection child;
@override
......
......@@ -2,30 +2,42 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.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);
/// 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.
/// In this case the Scrollable's scrollOffset will still over- and undershoot
/// the ScrollBehavior's limits, but the viewport itself will not.
class ClampOverscrolls extends InheritedWidget {
/// Creates a widget that controls whether [Scrollable] descendants will overscroll.
///
/// The [value] and [child] arguments must not be null.
ClampOverscrolls({
Key key,
this.value,
Widget child
@required this.value,
@required Widget child
}) : super(key: key, child: child) {
assert(value != null);
assert(child != null);
}
/// True if the [Scrollable] descendant should clamp its viewport's scrollOffset
/// values when they are less than the [ScrollBehavior]'s minimum or greater than
/// its maximum.
/// Whether [Scrollable] descendants should clamp their viewport's
/// scrollOffset values when they are less than the [ScrollBehavior]'s minimum
/// or greater than its maximum.
final bool value;
/// Whether a [Scrollable] widget within the given context should overscroll.
static bool of(BuildContext context) {
final ClampOverscrolls result = context.inheritFromWidgetOfExactType(ClampOverscrolls);
return result?.value ?? false;
......@@ -48,7 +60,6 @@ class ClampOverscrolls extends InheritedWidget {
return viewport;
}
@override
bool updateShouldNotify(ClampOverscrolls old) => value != old.value;
......
......@@ -101,6 +101,12 @@ bool debugCheckHasTable(BuildContext context) {
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) {
assert(() {
if (built == null) {
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.dart';
import 'transitions.dart';
import 'framework.dart';
......@@ -14,6 +16,7 @@ const double _kMinFlingVelocityDelta = 400.0;
const double _kFlingVelocityScale = 1.0 / 300.0;
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);
/// The direction in which a [Dismissable] can be dismissed.
......@@ -39,7 +42,7 @@ enum DismissDirection {
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
/// to slide out of view. Following the slide animation, if [resizeDuration] is
......@@ -56,8 +59,16 @@ enum DismissDirection {
/// 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.
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({
Key key,
@required Key key,
this.child,
this.background,
this.secondaryBackground,
......
......@@ -5,18 +5,29 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'basic.dart';
import 'binding.dart';
import 'framework.dart';
import 'overlay.dart';
/// Signature for determining whether the given data will be accepted by a [DragTarget].
typedef bool DragTargetWillAccept<T>(T data);
/// Signature for causing a [DragTarget] to accept the given 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);
/// Called when a [Draggable] is dropped without being accepted by a [DragTarget].
typedef void OnDraggableCanceled(Velocity velocity, Offset offset);
/// Signature for when a [Draggable] is dropped without being accepted by a [DragTarget].
typedef void DraggableCanceledCallback(Velocity velocity, Offset offset);
/// Where the [Draggable] should be anchored during a drag.
enum DragAnchor {
......@@ -40,12 +51,16 @@ enum DragAnchor {
/// Subclass this widget to customize the gesture used to start a drag.
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({
Key key,
@required this.child,
@required this.feedback,
this.data,
this.child,
this.childWhenDragging,
this.feedback,
this.feedbackOffset: Offset.zero,
this.dragAnchor: DragAnchor.child,
this.maxSimultaneousDrags,
......@@ -56,6 +71,7 @@ abstract class DraggableBase<T> extends StatefulWidget {
assert(maxSimultaneousDrags == null || maxSimultaneousDrags > 0);
}
/// The data that will be dropped by this draggable.
final T data;
/// The widget below this widget in the tree.
......@@ -85,7 +101,7 @@ abstract class DraggableBase<T> extends StatefulWidget {
final int maxSimultaneousDrags;
/// Called when the draggable is dropped without being accepted by a [DragTarget].
final OnDraggableCanceled onDraggableCanceled;
final DraggableCanceledCallback onDraggableCanceled;
/// Should return a new MultiDragGestureRecognizer instance
/// constructed with the given arguments.
......@@ -97,22 +113,26 @@ abstract class DraggableBase<T> extends StatefulWidget {
/// Makes its child draggable starting from tap down.
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({
Key key,
@required Widget child,
@required Widget feedback,
T data,
Widget child,
Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled
DraggableCanceledCallback onDraggableCanceled
}) : super(
key: key,
data: data,
child: child,
childWhenDragging: childWhenDragging,
feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags,
......@@ -128,22 +148,26 @@ class Draggable<T> extends DraggableBase<T> {
/// Makes its child draggable. When competing with other gestures,
/// this will only start the drag horizontally.
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({
Key key,
@required Widget child,
@required Widget feedback,
T data,
Widget child,
Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled
DraggableCanceledCallback onDraggableCanceled
}) : super(
key: key,
data: data,
child: child,
childWhenDragging: childWhenDragging,
feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags,
......@@ -159,22 +183,26 @@ class HorizontalDraggable<T> extends DraggableBase<T> {
/// Makes its child draggable. When competing with other gestures,
/// this will only start the drag vertically.
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({
Key key,
@required Widget child,
@required Widget feedback,
T data,
Widget child,
Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled
DraggableCanceledCallback onDraggableCanceled
}) : super(
key: key,
data: data,
child: child,
childWhenDragging: childWhenDragging,
feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags,
......@@ -189,22 +217,26 @@ class VerticalDraggable<T> extends DraggableBase<T> {
/// Makes its child draggable starting from long press.
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({
Key key,
@required Widget child,
@required Widget feedback,
T data,
Widget child,
Widget childWhenDragging,
Widget feedback,
Offset feedbackOffset: Offset.zero,
DragAnchor dragAnchor: DragAnchor.child,
int maxSimultaneousDrags,
OnDraggableCanceled onDraggableCanceled
DraggableCanceledCallback onDraggableCanceled
}) : super(
key: key,
data: data,
child: child,
childWhenDragging: childWhenDragging,
feedback: feedback,
data: data,
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
maxSimultaneousDrags: maxSimultaneousDrags,
......@@ -224,7 +256,6 @@ class LongPressDraggable<T> extends DraggableBase<T> {
}
class _DraggableState<T> extends State<DraggableBase<T>> {
@override
void initState() {
super.initState();
......@@ -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 {
/// Creates a widget that receives drags.
///
/// The [builder] argument must not be null.
const DragTarget({
Key key,
this.builder,
@required this.builder,
this.onWillAccept,
this.onAccept
}) : super(key: key);
......
......@@ -5,8 +5,9 @@
import 'dart:async';
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:meta/meta.dart';
import 'package:sky_services/editing/editing.mojom.dart' as mojom;
import 'basic.dart';
import 'framework.dart';
......@@ -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 {
/// 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({
this.text: '',
this.selection: const TextSelection.collapsed(offset: -1),
......@@ -99,9 +109,10 @@ class InputValue {
/// The range of text that is currently selected.
final TextSelection selection;
// The range of text that is still being composed.
/// The range of text that is still being composed.
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();
@override
......@@ -145,9 +156,12 @@ class InputValue {
/// This control is not intended to be used directly. Instead, consider using
/// [Input], which provides focus management and material design.
class RawInputLine extends Scrollable {
/// Creates a basic single-line input control.
///
/// The [value] argument must not be null.
RawInputLine({
Key key,
this.value,
@required this.value,
this.focusKey,
this.hideText: false,
this.style,
......@@ -162,7 +176,9 @@ class RawInputLine extends Scrollable {
key: key,
initialScrollOffset: 0.0,
scrollDirection: Axis.horizontal
);
) {
assert(value != null);
}
/// The string being displayed in this widget.
final InputValue value;
......@@ -203,6 +219,7 @@ class RawInputLine extends Scrollable {
RawInputLineState createState() => new RawInputLineState();
}
/// State for a [RawInputLine].
class RawInputLineState extends ScrollableState<RawInputLine> {
Timer _cursorTimer;
bool _showCursor = false;
......@@ -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() {
if (_isAttachedToKeyboard) {
_keyboardHandle.show();
......
......@@ -4,6 +4,8 @@
import 'dart:async';
import 'package:meta/meta.dart';
import 'basic.dart';
import 'framework.dart';
import 'media_query.dart';
......@@ -94,8 +96,11 @@ class _FocusScope extends InheritedWidget {
/// widgets), then the widget this this global key actually has the focus in the
/// entire system.
class Focus extends StatefulWidget {
/// Creates a scope for managing focus.
///
/// The [key] argument must not be null.
Focus({
GlobalKey key,
@required GlobalKey key,
this.child
}) : super(key: key) {
assert(key != null);
......
......@@ -2,14 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.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 {
/// Creates a container for form fields.
///
/// The [child] argument must not be null.
Form({
Key key,
this.child,
@required this.child,
this.onSubmitted
}) : super(key: key) {
assert(child != null);
......@@ -28,7 +34,7 @@ class Form extends StatefulWidget {
class _FormState extends State<Form> {
int generation = 0;
void onFieldChanged() {
void _onFieldChanged() {
setState(() {
++generation;
});
......@@ -36,20 +42,23 @@ class _FormState extends State<Form> {
@override
Widget build(BuildContext context) {
return new FormScope(
state: this,
return new FormScope._(
formState: this,
generation: generation,
child: config.child
);
}
}
/// Signature for validating a form field.
typedef String FormFieldValidator<T>(T value);
/// Signature for being notified when a form field changes value.
typedef void FormFieldSetter<T>(T newValue);
/// This contains identifying information for Input fields, required if the
/// Input is part of a Form.
/// Identifying information for form controls.
class FormField<T> {
/// Creates identifying information for form controls
FormField({
this.setter,
this.validator
......@@ -63,29 +72,32 @@ class FormField<T> {
final FormFieldValidator<T> validator;
}
/// The root of all Forms. Used by form field widgets (e.g. Input) to
/// communicate changes back to the client.
/// A widget that establishes a scope for a [Form].
///
/// Cannot be created directly. Instead, create a [Form] widget, which builds
/// a [FormScope].
///
/// Useful for locating the closest enclosing [Form].
class FormScope extends InheritedWidget {
FormScope({
FormScope._({
Key key,
Widget child,
_FormState state,
_FormState formState,
int generation
}) : _state = state,
}) : _formState = formState,
_generation = generation,
super(key: key, child: child);
final _FormState _state;
final _FormState _formState;
/// Incremented every time a form field has changed. This lets us know when
/// to rebuild the form.
final int _generation;
/// The Form this widget belongs to.
Form get form => _state.config;
/// The [Form] associated with this widget.
Form get form => _formState.config;
/// Finds the FormScope that encloses the widget being built from the given
/// context.
/// The closest [FormScope] encloses the given context.
static FormScope of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FormScope);
}
......@@ -93,7 +105,7 @@ class FormScope extends InheritedWidget {
/// 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
/// interdependencies.
void onFieldChanged() => _state.onFieldChanged();
void onFieldChanged() => _formState._onFieldChanged();
@override
bool updateShouldNotify(FormScope old) => _generation != old._generation;
......
......@@ -28,6 +28,10 @@ export 'package:flutter/gestures.dart' show
GestureScaleEndCallback,
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);
/// A widget that detects gestures.
......@@ -40,6 +44,17 @@ typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer)
///
/// See http://flutter.io/gestures/ for additional information.
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({
Key key,
this.child,
......@@ -296,6 +311,10 @@ class GestureDetector extends StatelessWidget {
/// RawGestureDetector is useful primarily when developing your
/// own gesture recognizers.
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({
Key key,
this.child,
......@@ -310,6 +329,7 @@ class RawGestureDetector extends StatefulWidget {
/// The widget below this widget in the tree.
final Widget child;
/// The gestures that this widget will attempt to recognize.
final Map<Type, GestureRecognizerFactory> gestures;
/// How this gesture detector should behave during hit testing.
......@@ -326,8 +346,8 @@ class RawGestureDetector extends StatefulWidget {
RawGestureDetectorState createState() => new RawGestureDetectorState();
}
/// State for a [RawGestureDetector].
class RawGestureDetectorState extends State<RawGestureDetector> {
Map<Type, GestureRecognizer> _recognizers = const <Type, GestureRecognizer>{};
@override
......
......@@ -47,9 +47,11 @@ class _GridPaperPainter extends CustomPainter {
bool hitTest(Point position) => false;
}
/// Draws a rectalinear grid of 1px width lines at the specified color and interval.
/// Useful with a Stack for visualizing your layout along a grid.
/// A widget that draws a rectilinear grid of 1px wide lines.
///
/// Useful with a [Stack] for visualizing your layout along a grid.
class GridPaper extends StatelessWidget {
/// Creates a widget that draws a rectilinear grid of 1px wide lines.
GridPaper({
Key key,
this.color: const Color(0x7FC3E8F3),
......
......@@ -5,10 +5,14 @@
import 'basic.dart';
import 'framework.dart';
import 'package:meta/meta.dart';
import 'package:vector_math/vector_math_64.dart';
/// An interpolation between two [BoxConstraint]s.
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);
@override
......@@ -17,6 +21,9 @@ class BoxConstraintsTween extends Tween<BoxConstraints> {
/// An interpolation between two [Decoration]s.
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);
@override
......@@ -25,6 +32,9 @@ class DecorationTween extends Tween<Decoration> {
/// An interpolation between two [EdgeInsets]s.
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);
@override
......@@ -35,12 +45,15 @@ class EdgeInsetsTween extends Tween<EdgeInsets> {
///
/// Currently this class works only for translations.
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);
@override
Matrix4 lerp(double t) {
// TODO(mpcomplete): Animate the full matrix. Will animating the cells
// separately work?
// TODO(abarth): We should use [Matrix4.decompose] and animate the
// decomposed parameters instead of just animating the translation.
Vector3 beginT = begin.getTranslation();
Vector3 endT = end.getTranslation();
Vector3 lerpT = beginT*(1.0-t) + endT*t;
......@@ -52,6 +65,9 @@ class Matrix4Tween extends Tween<Matrix4> {
///
/// This will not work well if the styles don't set the same fields.
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);
@override
......@@ -61,10 +77,13 @@ class TextStyleTween extends Tween<TextStyle> {
/// An abstract widget for building widgets that gradually change their
/// values over a period of time.
abstract class ImplicitlyAnimatedWidget extends StatefulWidget {
/// Initializes fields for subclasses.
///
/// The [curve] and [duration] arguments must not be null.
ImplicitlyAnimatedWidget({
Key key,
this.curve: Curves.linear,
this.duration
@required this.duration
}) : super(key: key) {
assert(curve != null);
assert(duration != null);
......@@ -196,6 +215,9 @@ abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> exten
/// likely want to use a subclass of [Transition] or use an
/// [AnimationController] yourself.
class AnimatedContainer extends ImplicitlyAnimatedWidget {
/// Creates a container that animates its parameters implicitly.
///
/// The [curve] and [duration] arguments must not be null.
AnimatedContainer({
Key key,
this.child,
......@@ -208,7 +230,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
this.width,
this.height,
Curve curve: Curves.linear,
Duration duration
@required Duration duration
}) : super(key: key, curve: curve, duration: duration) {
assert(decoration == null || decoration.debugAssertValid());
assert(foregroundDecoration == null || foregroundDecoration.debugAssertValid());
......@@ -333,6 +355,14 @@ class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer>
///
/// Only works if it's the child of a [Stack].
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({
Key key,
this.child,
......@@ -343,18 +373,21 @@ class AnimatedPositioned extends ImplicitlyAnimatedWidget {
this.width,
this.height,
Curve curve: Curves.linear,
Duration duration
@required Duration duration
}) : super(key: key, curve: curve, duration: duration) {
assert(left == null || right == null || width == 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({
Key key,
this.child,
Rect rect,
Curve curve: Curves.linear,
Duration duration
@required Duration duration
}) : left = rect.left,
top = rect.top,
width = rect.width,
......@@ -466,12 +499,16 @@ class _AnimatedPositionedState extends AnimatedWidgetBaseState<AnimatedPositione
///
/// Animating an opacity is relatively expensive.
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({
Key key,
this.child,
this.opacity,
Curve curve: Curves.linear,
Duration duration
@required Duration duration
}) : super(key: key, curve: curve, duration: duration) {
assert(opacity != null && opacity >= 0.0 && opacity <= 1.0);
}
......@@ -520,12 +557,15 @@ class _AnimatedOpacityState extends AnimatedWidgetBaseState<AnimatedOpacity> {
/// descendant [Text] widgets without explicit style) over a given
/// duration whenever the given style changes.
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({
Key key,
this.child,
this.style,
@required this.child,
@required this.style,
Curve curve: Curves.linear,
Duration duration
@required Duration duration
}) : super(key: key, curve: curve, duration: duration) {
assert(style != null);
assert(child != null);
......
......@@ -6,6 +6,7 @@ import 'debug.dart';
import 'framework.dart';
import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart';
/// The signature of the [LayoutBuilder] builder function.
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
/// intrinsic size.
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);
}
......
......@@ -5,6 +5,7 @@
import 'dart:math' as math;
import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart';
import 'basic.dart';
import 'clamp_overscrolls.dart';
......@@ -133,8 +134,12 @@ class LazyBlockChildren extends LazyBlockDelegate {
/// it can use that property to be more efficient. Prefer [ScrollableViewport]
/// when there is only one child.
class LazyBlock extends StatelessWidget {
/// Creates an infinite scrolling list of variable height children.
///
/// The [delegate] argument must not be null.
LazyBlock({
Key key,
@required this.delegate,
this.initialScrollOffset,
this.scrollDirection: Axis.vertical,
this.onScrollStart,
......@@ -142,9 +147,10 @@ class LazyBlock extends StatelessWidget {
this.onScrollEnd,
this.snapOffsetCallback,
this.scrollableKey,
this.padding,
this.delegate
}) : super(key: key);
this.padding
}) : super(key: key) {
assert(delegate != null);
}
// Warning: keep the dartdoc comments that follow in sync with the copies in
// Scrollable, ScrollableGrid, ScrollableViewport, ScrollableList, and
......@@ -276,13 +282,16 @@ typedef void LazyBlockExtentsChangedCallback(double contentExtent, double contai
///
/// For a scrollable version of this widget, see [LazyBlock].
class LazyBlockViewport extends RenderObjectWidget {
/// Creates a viewport on an infinite list of variable height children.
///
/// The [delegate] argument must not be null.
LazyBlockViewport({
Key key,
@required this.delegate,
this.startOffset: 0.0,
this.mainAxis: Axis.vertical,
this.padding,
this.onExtentsChanged,
this.delegate
this.onExtentsChanged
}) : super(key: key) {
assert(delegate != null);
}
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart';
/// 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'
/// Establishes a subtree in which locale queries resolve to the given data.
class LocaleQuery extends InheritedWidget {
/// Creates a widget that provides [LocaleQueryData] to its descendants.
LocaleQuery({
Key key,
this.data,
Widget child
@required this.data,
@required Widget child
}) : super(key: key, child: child) {
assert(child != null);
}
......
......@@ -4,6 +4,8 @@
import 'dart:ui' as ui;
import 'package:meta/meta.dart';
import 'basic.dart';
import 'framework.dart';
......@@ -74,10 +76,13 @@ class MediaQueryData {
/// Establishes a subtree in which media queries resolve to the given data.
class MediaQuery extends InheritedWidget {
/// Creates a widget that provides [MediaQueryData] to its descendants.
///
/// The [data] and [child] arguments must not be null.
MediaQuery({
Key key,
this.data,
Widget child
@required this.data,
@required Widget child
}) : super(key: key, child: child) {
assert(child != null);
assert(data != null);
......
......@@ -124,6 +124,7 @@ class MimicOverlayEntry {
/// A widget that copies the appearance of another widget.
class Mimic extends StatelessWidget {
/// Creates a widget that copies the appearance of another widget.
Mimic({ Key key, this.original }) : super(key: key);
/// A handle to the widget that this widget should copy.
......@@ -142,6 +143,7 @@ class Mimic extends StatelessWidget {
/// This widget's State, [MimicableState], contains an API for initiating the
/// mimic operation.
class Mimicable extends StatefulWidget {
/// Creates a widget that can be copies by a [Mimic].
Mimicable({ Key key, this.child }) : super(key: key);
/// The widget below this widget in the tree.
......
......@@ -8,8 +8,9 @@ import 'gesture_detector.dart';
import 'navigator.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 {
/// Creates a widget that blocks user interaction.
ModalBarrier({
Key key,
this.color,
......@@ -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 {
/// Creates a widget that blocks user interaction.
AnimatedModalBarrier({
Key key,
Animation<Color> color,
......@@ -62,7 +64,7 @@ class AnimatedModalBarrier extends AnimatedWidget {
@override
Widget build(BuildContext context) {
return new ModalBarrier(
color: color.value,
color: color?.value,
dismissable: dismissable
);
}
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart';
import 'overlay.dart';
......@@ -79,6 +81,7 @@ abstract class Route<T> {
/// Data that might be useful in constructing a [Route].
class RouteSettings {
/// Creates data used to construct routes.
const RouteSettings({
this.name,
this.mostValuableKeys,
......@@ -86,6 +89,8 @@ class RouteSettings {
});
/// The name of the route (e.g., "/settings").
///
/// If null, the route is anonymous.
final String name;
/// The set of keys that are most relevant for constructoring [Hero]
......@@ -132,7 +137,7 @@ class NavigatorObserver {
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
/// to display their logical history using an [Overlay] with the most recently
......@@ -141,10 +146,13 @@ class NavigatorObserver {
/// around in the overlay. Similarly, the navigator can be used to show a dialog
/// by positioning the dialog widget above the current page.
class Navigator extends StatefulWidget {
/// Creates a widget that maintains a stack-based history of child widgets.
///
/// The [onGenerateRoute] argument must not be null.
Navigator({
Key key,
this.initialRoute,
this.onGenerateRoute,
@required this.onGenerateRoute,
this.onUnknownRoute,
this.observer
}) : super(key: key) {
......
......@@ -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 {
/// Creates a widget that listens for notifications.
NotificationListener({
Key key,
this.child,
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'basic.dart';
import 'framework.dart';
......@@ -42,7 +44,7 @@ class OverlayEntry {
/// [Overlay.of] and then call [OverlayState.insert]. To remove the entry,
/// call [remove] on the overlay entry itself.
OverlayEntry({
this.builder,
@required this.builder,
bool opaque: false
}) : _opaque = opaque {
assert(builder != null);
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart';
class _StorageEntryIdentifier {
......@@ -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 {
/// Creates a widget that provides a storage bucket for its descendants.
///
/// The [bucket] argument must not be null.
PageStorage({
Key key,
this.child,
this.bucket
}) : super(key: key);
@required this.bucket,
this.child
}) : super(key: key) {
assert(bucket != null);
}
/// The widget below this widget in the tree.
final Widget child;
......
......@@ -14,12 +14,39 @@ import 'virtual_viewport.dart';
/// Controls how a pageable list should behave during a fling.
enum PageableListFlingBehavior {
/// A fling gesture can scroll the list by more than one page.
canFlingAcrossMultiplePages,
/// A fling gesture can scroll the list by at most one page.
stopAtNextPage
}
abstract class PageableListBase extends Scrollable {
PageableListBase({
/// A base class for widgets that display one page at a time.
///
/// [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,
double initialScrollOffset,
Axis scrollDirection: Axis.vertical,
......@@ -64,11 +91,21 @@ abstract class PageableListBase extends Scrollable {
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
/// reveals either the next or previous child.
class PageableList extends PageableListBase {
/// 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:
///
/// * [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({
Key key,
double initialScrollOffset,
......@@ -110,7 +147,20 @@ class PageableList extends PageableListBase {
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({
Key key,
double initialScrollOffset,
......@@ -155,7 +205,12 @@ class PageableLazyList extends PageableListBase {
_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 _previousItemCount;
......@@ -202,7 +257,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll
}
@override
void didUpdateConfig(PageableListBase oldConfig) {
void didUpdateConfig(Pageable oldConfig) {
super.didUpdateConfig(oldConfig);
bool scrollBehaviorUpdateNeeded = config.scrollDirection != oldConfig.scrollDirection;
......@@ -287,7 +342,7 @@ abstract class _PageableListStateBase<T extends PageableListBase> extends Scroll
///
/// Widgets that subclass [PageableList] can subclass this class to have
/// sensible default behaviors for pageable lists.
class PageableListState<T extends PageableList> extends _PageableListStateBase<T> {
class PageableListState<T extends PageableList> extends PageableState<T> {
@override
Widget buildContent(BuildContext context) {
return new PageViewport(
......@@ -300,7 +355,7 @@ class PageableListState<T extends PageableList> extends _PageableListStateBase<T
}
}
class _PageableLazyListState extends _PageableListStateBase<PageableLazyList> {
class _PageableLazyListState extends PageableState<PageableLazyList> {
@override
Widget buildContent(BuildContext context) {
return new LazyPageViewport(
......@@ -321,13 +376,37 @@ class _VirtualPageViewport extends VirtualViewport {
this.itemsWrap
) {
assert(mainAxis != null);
assert(anchor != null);
}
@override
final double startOffset;
/// The axis along which the viewport is bigger on the inside than the outside.
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;
/// Whether the first item should be revealed after scrolling past the last item.
final bool itemsWrap;
@override
......@@ -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 {
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
PageViewport({
double startOffset: 0.0,
Axis mainAxis: Axis.vertical,
......@@ -451,7 +544,22 @@ class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable
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 {
/// Creates a virtual viewport that displays a single child at a time.
///
/// The [mainAxis] and [anchor] arguments must not be null.
LazyPageViewport({
double startOffset: 0.0,
Axis mainAxis: Axis.vertical,
......
......@@ -11,6 +11,7 @@ import 'routes.dart';
/// A modal route that replaces the entire screen.
abstract class PageRoute<T> extends ModalRoute<T> {
/// Creates a modal route that replaces the entire screen.
PageRoute({
Completer<T> completer,
RouteSettings settings: const RouteSettings()
......
......@@ -27,7 +27,11 @@ class PerformanceOverlay extends LeafRenderObjectWidget {
/// Create a performance overlay that only displays specific statistics. The
/// mask is created by shifting 1 by the index of the specific
/// [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
PerformanceOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 })
......
......@@ -7,6 +7,7 @@ import 'framework.dart';
/// A widget whose child can be mutated.
class Placeholder extends StatefulWidget {
/// Creates a widget whose child can be mutated.
Placeholder({ Key key }) : super(key: key);
@override
......
......@@ -9,7 +9,24 @@ import 'package:sky_services/sky/input_event.mojom.dart' as mojom;
import 'basic.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 {
/// 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({
Key key,
this.focused: false,
......@@ -19,8 +36,13 @@ class RawKeyboardListener extends StatefulWidget {
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;
/// Called whenever this widget receives a raw keyboard event.
final ValueChanged<mojom.InputEvent> onKey;
/// The widget below this widget in the tree.
......
......@@ -69,6 +69,7 @@ abstract class OverlayRoute<T> extends Route<T> {
/// A route with entrance and exit transitions.
abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// Creates a route with entrance and exit transitions.
TransitionRoute({
Completer<T> popCompleter,
Completer<T> transitionCompleter
......@@ -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;
final ProxyAnimation _forwardAnimation = new ProxyAnimation(kAlwaysDismissedAnimation);
......@@ -246,6 +250,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
super.dispose();
}
/// A short description of this route useful for debugging.
String get debugLabel => '$runtimeType';
@override
......@@ -254,6 +259,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// An entry in the history of a [LocalHistoryRoute].
class LocalHistoryEntry {
/// Creates an entry in the history of a [LocalHistoryRoute].
LocalHistoryEntry({ this.onRemove });
/// Called when this entry is removed from the history of its associated [LocalHistoryRoute].
......@@ -439,6 +445,7 @@ class _ModalScopeState extends State<_ModalScope> {
/// however; for example, a pop-up menu uses a ModalRoute but only shows the menu
/// in a small box overlapping the previous route.
abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T> {
/// Creates a route that blocks interaction with previous routes.
ModalRoute({
Completer<T> completer,
this.settings: const RouteSettings()
......@@ -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.
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);
@override
......
......@@ -5,6 +5,7 @@
import 'dart:math' as math;
import 'package:flutter/physics.dart';
import 'package:meta/meta.dart';
const double _kSecondsPerMillisecond = 1000.0;
const double _kScrollDrag = 0.025;
......@@ -47,6 +48,12 @@ abstract class ScrollBehavior<T, U> {
debugFillDescription(description);
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) {
description.add(isScrollable ? 'scrollable' : 'not scrollable');
}
......@@ -55,6 +62,7 @@ abstract class ScrollBehavior<T, U> {
/// A scroll behavior for a scrollable widget with linear extent (i.e.
/// that only scrolls along one axis).
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 })
: _contentExtent = contentExtent, _containerExtent = containerExtent;
......@@ -102,6 +110,7 @@ abstract class ExtentScrollBehavior extends ScrollBehavior<double, double> {
/// A scroll behavior that prevents the user from exceeding scroll bounds.
class BoundedBehavior extends ExtentScrollBehavior {
/// Creates a scroll behavior that does not overscroll.
BoundedBehavior({
double contentExtent: 0.0,
double containerExtent: 0.0,
......@@ -154,6 +163,7 @@ Simulation _createSnapScrollSimulation(double startOffset, double endOffset, dou
/// A scroll behavior that does not prevent the user from exeeding scroll bounds.
class UnboundedBehavior extends ExtentScrollBehavior {
/// Creates a scroll behavior with no scrolling limits.
UnboundedBehavior({ double contentExtent: 0.0, double containerExtent: 0.0 })
: super(contentExtent: contentExtent, containerExtent: containerExtent);
......@@ -184,6 +194,7 @@ class UnboundedBehavior extends ExtentScrollBehavior {
/// A scroll behavior that lets the user scroll beyond the scroll bounds with some resistance.
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 })
: super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset);
......@@ -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.
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 })
: super(contentExtent: contentExtent, containerExtent: containerExtent, minScrollOffset: minScrollOffset);
......
......@@ -5,7 +5,13 @@
import 'framework.dart';
import 'scroll_behavior.dart';
/// Controls how [Scrollable] widgets in a subtree behave.
///
/// Used by [ScrollConfiguration].
class ScrollConfigurationDelegate {
/// Creates a delegate with sensible default behaviors.
const ScrollConfigurationDelegate();
/// Returns the ScrollBehavior to be used by generic scrolling containers like
/// [Block]. Returns a new [OverscrollWhenScrollableBehavior] by default.
ExtentScrollBehavior createScrollBehavior() => new OverscrollWhenScrollableBehavior();
......@@ -22,14 +28,13 @@ class ScrollConfigurationDelegate {
bool updateShouldNotify(ScrollConfigurationDelegate old) => false;
}
/// Used by descendants to initialize and wrap the [Scrollable] widgets
/// they create.
/// A widget that controls descendant [Scrollable] widgets.
///
/// Classes that create Scrollables are not required to depend on this
/// Widget. The following general purpose scrolling widgets do depend
/// on ScrollConfiguration: Block, LazyBlock, ScrollableViewport,
/// ScrollableList, ScrollableLazyList. The Scrollable base class uses
/// ScrollConfiguration to create its [ScrollBehavior].
/// on [ScrollConfiguration]: [Block], [LazyBlock], [ScrollableViewport],
/// [ScrollableList], [ScrollableLazyList]. The [Scrollable] base class uses
/// [ScrollConfiguration] to create its [ScrollBehavior].
class ScrollConfiguration extends InheritedWidget {
ScrollConfiguration({
Key key,
......@@ -37,7 +42,7 @@ class ScrollConfiguration extends InheritedWidget {
Widget 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.
final ScrollConfigurationDelegate delegate;
......
......@@ -38,6 +38,9 @@ typedef double SnapOffsetCallback(double scrollOffset, Size containerSize);
/// Widgets that subclass [Scrollable] typically use state objects that subclass
/// [ScrollableState].
class Scrollable extends StatefulWidget {
/// Initializes fields for subclasses.
///
/// The [scrollDirection] and [scrollAnchor] arguments must not be null.
Scrollable({
Key key,
this.initialScrollOffset,
......
......@@ -274,6 +274,9 @@ class FadeTransition extends AnimatedWidget {
/// appropriate for rectangles that are described in terms of offsets from
/// other rectangles.
class RelativeRectTween extends Tween<RelativeRect> {
/// Creates a relative rect tween.
///
/// The [begin] and [end] arguments must not be null.
RelativeRectTween({ RelativeRect begin, RelativeRect end })
: super(begin: begin, end: end);
......
......@@ -2,11 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'framework.dart';
/// A widget that has exactly one inflated instance in the tree.
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);
}
......@@ -14,6 +22,8 @@ abstract class UniqueWidget<T extends State> extends StatefulWidget {
T createState();
/// 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 {
GlobalKey globalKey = key;
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