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