Mark most State subclasses private

In the vast majority of cases, folks should be interacting with the Widget
rather than its State.

Fixes #267
This commit is contained in:
Adam Barth 2015-10-05 21:54:33 -07:00
parent 330af86bdc
commit 922aece1d5
27 changed files with 154 additions and 160 deletions

View File

@ -77,10 +77,10 @@ class AnimatedContainer extends StatefulComponent {
final Curve curve; final Curve curve;
final Duration duration; final Duration duration;
AnimatedContainerState createState() => new AnimatedContainerState(); _AnimatedContainerState createState() => new _AnimatedContainerState();
} }
class AnimatedContainerState extends State<AnimatedContainer> { class _AnimatedContainerState extends State<AnimatedContainer> {
AnimatedBoxConstraintsValue _constraints; AnimatedBoxConstraintsValue _constraints;
AnimatedBoxDecorationValue _decoration; AnimatedBoxDecorationValue _decoration;
AnimatedBoxDecorationValue _foregroundDecoration; AnimatedBoxDecorationValue _foregroundDecoration;

View File

@ -47,10 +47,10 @@ class App extends StatefulComponent {
final Map<String, RouteBuilder> routes; final Map<String, RouteBuilder> routes;
final RouteGenerator onGenerateRoute; final RouteGenerator onGenerateRoute;
AppState createState() => new AppState(); _AppState createState() => new _AppState();
} }
class AppState extends State<App> { class _AppState extends State<App> {
GlobalObjectKey _navigator; GlobalObjectKey _navigator;

View File

@ -808,10 +808,10 @@ class ImageListener extends StatefulComponent {
final ImageFit fit; final ImageFit fit;
final ImageRepeat repeat; final ImageRepeat repeat;
ImageListenerState createState() => new ImageListenerState(); _ImageListenerState createState() => new _ImageListenerState();
} }
class ImageListenerState extends State<ImageListener> { class _ImageListenerState extends State<ImageListener> {
void initState() { void initState() {
super.initState(); super.initState();
config.image.addListener(_handleImageChanged); config.image.addListener(_handleImageChanged);

View File

@ -39,10 +39,10 @@ class DatePicker extends StatefulComponent {
final DateTime firstDate; final DateTime firstDate;
final DateTime lastDate; final DateTime lastDate;
DatePickerState createState() => new DatePickerState(); _DatePickerState createState() => new _DatePickerState();
} }
class DatePickerState extends State<DatePicker> { class _DatePickerState extends State<DatePicker> {
DatePickerMode _mode = DatePickerMode.day; DatePickerMode _mode = DatePickerMode.day;
void _handleModeChanged(DatePickerMode mode) { void _handleModeChanged(DatePickerMode mode) {
@ -70,7 +70,7 @@ class DatePickerState extends State<DatePicker> {
static const double _calendarHeight = 210.0; static const double _calendarHeight = 210.0;
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget header = new DatePickerHeader( Widget header = new _DatePickerHeader(
selectedDate: config.selectedDate, selectedDate: config.selectedDate,
mode: _mode, mode: _mode,
onModeChanged: _handleModeChanged onModeChanged: _handleModeChanged
@ -107,8 +107,8 @@ class DatePickerState extends State<DatePicker> {
} }
// Shows the selected date in large font and toggles between year and day mode // Shows the selected date in large font and toggles between year and day mode
class DatePickerHeader extends StatelessComponent { class _DatePickerHeader extends StatelessComponent {
DatePickerHeader({ this.selectedDate, this.mode, this.onModeChanged }) { _DatePickerHeader({ this.selectedDate, this.mode, this.onModeChanged }) {
assert(selectedDate != null); assert(selectedDate != null);
assert(mode != null); assert(mode != null);
} }
@ -290,10 +290,10 @@ class MonthPicker extends ScrollableWidgetList {
final DateTime firstDate; final DateTime firstDate;
final DateTime lastDate; final DateTime lastDate;
MonthPickerState createState() => new MonthPickerState(); _MonthPickerState createState() => new _MonthPickerState();
} }
class MonthPickerState extends ScrollableWidgetListState<MonthPicker> { class _MonthPickerState extends ScrollableWidgetListState<MonthPicker> {
void initState() { void initState() {
super.initState(); super.initState();
_updateCurrentDate(); _updateCurrentDate();
@ -363,10 +363,10 @@ class YearPicker extends ScrollableWidgetList {
final DateTime firstDate; final DateTime firstDate;
final DateTime lastDate; final DateTime lastDate;
YearPickerState createState() => new YearPickerState(); _YearPickerState createState() => new _YearPickerState();
} }
class YearPickerState extends ScrollableWidgetListState<YearPicker> { class _YearPickerState extends ScrollableWidgetListState<YearPicker> {
int get itemCount => config.lastDate.year - config.firstDate.year + 1; int get itemCount => config.lastDate.year - config.firstDate.year + 1;
List<Widget> buildItems(BuildContext context, int start, int count) { List<Widget> buildItems(BuildContext context, int start, int count) {

View File

@ -131,16 +131,15 @@ class Dialog extends StatelessComponent {
} }
} }
const Duration _kTransitionDuration = const Duration(milliseconds: 150); class _DialogRoute extends Route {
_DialogRoute({ this.completer, this.builder });
class DialogRoute extends Route {
DialogRoute({ this.completer, this.builder });
final Completer completer; final Completer completer;
final RouteBuilder builder; final RouteBuilder builder;
Duration get transitionDuration => _kTransitionDuration;
bool get opaque => false; bool get opaque => false;
Duration get transitionDuration => const Duration(milliseconds: 150);
Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) { Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) {
return new FadeTransition( return new FadeTransition(
performance: performance, performance: performance,
@ -157,7 +156,7 @@ class DialogRoute extends Route {
Future showDialog(NavigatorState navigator, DialogBuilder builder) { Future showDialog(NavigatorState navigator, DialogBuilder builder) {
Completer completer = new Completer(); Completer completer = new Completer();
navigator.push(new DialogRoute( navigator.push(new _DialogRoute(
completer: completer, completer: completer,
builder: (RouteArguments args) { builder: (RouteArguments args) {
return new Focus( return new Focus(

View File

@ -39,15 +39,15 @@ class Dismissable extends StatefulComponent {
this.direction: DismissDirection.horizontal this.direction: DismissDirection.horizontal
}) : super(key: key); }) : super(key: key);
Widget child; final Widget child;
ResizedCallback onResized; final ResizedCallback onResized;
DismissedCallback onDismissed; final DismissedCallback onDismissed;
DismissDirection direction; final DismissDirection direction;
DismissableState createState() => new DismissableState(); _DismissableState createState() => new _DismissableState();
} }
class DismissableState extends State<Dismissable> { class _DismissableState extends State<Dismissable> {
void initState() { void initState() {
super.initState(); super.initState();
_fadePerformance = new Performance(duration: _kCardDismissFadeout); _fadePerformance = new Performance(duration: _kCardDismissFadeout);

View File

@ -62,10 +62,10 @@ class Draggable extends StatefulComponent {
final Offset feedbackOffset; final Offset feedbackOffset;
final DragAnchor dragAnchor; final DragAnchor dragAnchor;
DraggableState createState() => new DraggableState(); _DraggableState createState() => new _DraggableState();
} }
class DraggableState extends State<Draggable> { class _DraggableState extends State<Draggable> {
DragRoute _route; DragRoute _route;
void _startDrag(sky.PointerEvent event) { void _startDrag(sky.PointerEvent event) {

View File

@ -23,10 +23,10 @@ class DrawerItem extends StatefulComponent {
final GestureTapCallback onPressed; final GestureTapCallback onPressed;
final bool selected; final bool selected;
DrawerItemState createState() => new DrawerItemState(); _DrawerItemState createState() => new _DrawerItemState();
} }
class DrawerItemState extends ButtonState<DrawerItem> { class _DrawerItemState extends ButtonState<DrawerItem> {
TextStyle _getTextStyle(ThemeData themeData) { TextStyle _getTextStyle(ThemeData themeData) {
TextStyle result = themeData.text.body2; TextStyle result = themeData.text.body2;
if (config.selected) if (config.selected)

View File

@ -20,10 +20,10 @@ class FlatButton extends MaterialButton {
enabled: enabled, enabled: enabled,
onPressed: onPressed); onPressed: onPressed);
FlatButtonState createState() => new FlatButtonState(); _FlatButtonState createState() => new _FlatButtonState();
} }
class FlatButtonState extends MaterialButtonState<FlatButton> { class _FlatButtonState extends MaterialButtonState<FlatButton> {
Color getColor(BuildContext context) { Color getColor(BuildContext context) {
if (!config.enabled || !highlight) if (!config.enabled || !highlight)
return null; return null;

View File

@ -27,10 +27,10 @@ class FloatingActionButton extends StatefulComponent {
final Color backgroundColor; final Color backgroundColor;
final GestureTapCallback onPressed; final GestureTapCallback onPressed;
FloatingActionButtonState createState() => new FloatingActionButtonState(); _FloatingActionButtonState createState() => new _FloatingActionButtonState();
} }
class FloatingActionButtonState extends ButtonState<FloatingActionButton> { class _FloatingActionButtonState extends ButtonState<FloatingActionButton> {
Widget buildContent(BuildContext context) { Widget buildContent(BuildContext context) {
IconThemeColor iconThemeColor = IconThemeColor.white; IconThemeColor iconThemeColor = IconThemeColor.white;
Color materialColor = config.backgroundColor; Color materialColor = config.backgroundColor;

View File

@ -57,10 +57,10 @@ class GestureDetector extends StatefulComponent {
final GestureScaleUpdateCallback onScaleUpdate; final GestureScaleUpdateCallback onScaleUpdate;
final GestureScaleEndCallback onScaleEnd; final GestureScaleEndCallback onScaleEnd;
GestureDetectorState createState() => new GestureDetectorState(); _GestureDetectorState createState() => new _GestureDetectorState();
} }
class GestureDetectorState extends State<GestureDetector> { class _GestureDetectorState extends State<GestureDetector> {
final PointerRouter _router = FlutterBinding.instance.pointerRouter; final PointerRouter _router = FlutterBinding.instance.pointerRouter;
TapGestureRecognizer _tap; TapGestureRecognizer _tap;

View File

@ -30,7 +30,7 @@ class HomogeneousViewport extends RenderObjectWidget {
final ScrollDirection direction; final ScrollDirection direction;
final double startOffset; final double startOffset;
HomogeneousViewportElement createElement() => new HomogeneousViewportElement(this); _HomogeneousViewportElement createElement() => new _HomogeneousViewportElement(this);
// we don't pass constructor arguments to the RenderBlockViewport() because until // we don't pass constructor arguments to the RenderBlockViewport() because until
// we know our children, the constructor arguments we could give have no effect // we know our children, the constructor arguments we could give have no effect
@ -48,8 +48,8 @@ class HomogeneousViewport extends RenderObjectWidget {
// all the actual work is done in the element // all the actual work is done in the element
} }
class HomogeneousViewportElement extends RenderObjectElement<HomogeneousViewport> { class _HomogeneousViewportElement extends RenderObjectElement<HomogeneousViewport> {
HomogeneousViewportElement(HomogeneousViewport widget) : super(widget); _HomogeneousViewportElement(HomogeneousViewport widget) : super(widget);
List<Element> _children = const <Element>[]; List<Element> _children = const <Element>[];
int _layoutFirstIndex; int _layoutFirstIndex;

View File

@ -61,7 +61,7 @@ class Icon extends StatelessComponent {
final IconThemeColor color; final IconThemeColor color;
final sky.ColorFilter colorFilter; final sky.ColorFilter colorFilter;
String getColorSuffix(BuildContext context) { String _getColorSuffix(BuildContext context) {
IconThemeColor iconThemeColor = color; IconThemeColor iconThemeColor = color;
if (iconThemeColor == null) { if (iconThemeColor == null) {
IconThemeData iconThemeData = IconTheme.of(context); IconThemeData iconThemeData = IconTheme.of(context);
@ -90,7 +90,7 @@ class Icon extends StatelessComponent {
// TODO(eseidel): This clearly isn't correct. Not sure what would be. // TODO(eseidel): This clearly isn't correct. Not sure what would be.
// Should we use the ios images on ios? // Should we use the ios images on ios?
String density = 'drawable-xxhdpi'; String density = 'drawable-xxhdpi';
String colorSuffix = getColorSuffix(context); String colorSuffix = _getColorSuffix(context);
return new AssetImage( return new AssetImage(
bundle: _iconBundle, bundle: _iconBundle,
name: '${category}/${density}/ic_${subtype}_${colorSuffix}_${size}dp.png', name: '${category}/${density}/ic_${subtype}_${colorSuffix}_${size}dp.png',

View File

@ -26,8 +26,8 @@ double _getSplashTargetSize(Size bounds, Point position) {
return math.max(math.max(d1, d2), math.max(d3, d4)).ceil().toDouble(); return math.max(math.max(d1, d2), math.max(d3, d4)).ceil().toDouble();
} }
class InkSplash { class _InkSplash {
InkSplash(this.position, this.well) { _InkSplash(this.position, this.well) {
_targetRadius = _getSplashTargetSize(well.size, position); _targetRadius = _getSplashTargetSize(well.size, position);
_radius = new AnimatedValue<double>( _radius = new AnimatedValue<double>(
_kSplashInitialSize, end: _targetRadius, curve: easeOut); _kSplashInitialSize, end: _targetRadius, curve: easeOut);
@ -42,7 +42,7 @@ class InkSplash {
} }
final Point position; final Point position;
final RenderInkWell well; final _RenderInkWell well;
double _targetRadius; double _targetRadius;
double _pinnedRadius; double _pinnedRadius;
@ -98,8 +98,8 @@ class InkSplash {
} }
} }
class RenderInkWell extends RenderProxyBox { class _RenderInkWell extends RenderProxyBox {
RenderInkWell({ _RenderInkWell({
RenderBox child, RenderBox child,
GestureTapCallback onTap, GestureTapCallback onTap,
GestureLongPressCallback onLongPress GestureLongPressCallback onLongPress
@ -122,7 +122,7 @@ class RenderInkWell extends RenderProxyBox {
_syncLongPressRecognizer(); _syncLongPressRecognizer();
} }
final List<InkSplash> _splashes = new List<InkSplash>(); final List<_InkSplash> _splashes = new List<_InkSplash>();
TapGestureRecognizer _tap; TapGestureRecognizer _tap;
LongPressGestureRecognizer _longPress; LongPressGestureRecognizer _longPress;
@ -131,7 +131,7 @@ class RenderInkWell extends RenderProxyBox {
if (event.type == 'pointerdown' && (_tap != null || _longPress != null)) { if (event.type == 'pointerdown' && (_tap != null || _longPress != null)) {
_tap?.addPointer(event); _tap?.addPointer(event);
_longPress?.addPointer(event); _longPress?.addPointer(event);
_splashes.add(new InkSplash(entry.localPosition, this)); _splashes.add(new _InkSplash(entry.localPosition, this));
} }
} }
@ -196,7 +196,7 @@ class RenderInkWell extends RenderProxyBox {
canvas.save(); canvas.save();
canvas.translate(offset.dx, offset.dy); canvas.translate(offset.dx, offset.dy);
canvas.clipRect(Point.origin & size); canvas.clipRect(Point.origin & size);
for (InkSplash splash in _splashes) for (_InkSplash splash in _splashes)
splash.paint(canvas); splash.paint(canvas);
canvas.restore(); canvas.restore();
} }
@ -215,9 +215,9 @@ class InkWell extends OneChildRenderObjectWidget {
final GestureTapCallback onTap; final GestureTapCallback onTap;
final GestureLongPressCallback onLongPress; final GestureLongPressCallback onLongPress;
RenderInkWell createRenderObject() => new RenderInkWell(onTap: onTap, onLongPress: onLongPress); _RenderInkWell createRenderObject() => new _RenderInkWell(onTap: onTap, onLongPress: onLongPress);
void updateRenderObject(RenderInkWell renderObject, InkWell oldWidget) { void updateRenderObject(_RenderInkWell renderObject, InkWell oldWidget) {
renderObject.onTap = onTap; renderObject.onTap = onTap;
renderObject.onLongPress = onLongPress; renderObject.onLongPress = onLongPress;
} }

View File

@ -39,10 +39,10 @@ class Input extends Scrollable {
final String placeholder; final String placeholder;
final StringValueChanged onChanged; final StringValueChanged onChanged;
InputState createState() => new InputState(); _InputState createState() => new _InputState();
} }
class InputState extends ScrollableState<Input> { class _InputState extends ScrollableState<Input> {
String _value; String _value;
EditableString _editableValue; EditableString _editableValue;
KeyboardHandle _keyboardHandle = KeyboardHandle.unattached; KeyboardHandle _keyboardHandle = KeyboardHandle.unattached;

View File

@ -12,7 +12,7 @@ import 'package:sky/src/widgets/theme.dart';
enum MaterialType { canvas, card, circle, button } enum MaterialType { canvas, card, circle, button }
const Map<MaterialType, double> edges = const { const Map<MaterialType, double> _kEdges = const <MaterialType, double>{
MaterialType.canvas: null, MaterialType.canvas: null,
MaterialType.card: 2.0, MaterialType.card: 2.0,
MaterialType.circle: null, MaterialType.circle: null,
@ -35,7 +35,7 @@ class Material extends StatelessComponent {
final int level; final int level;
final Color color; final Color color;
Color getBackgroundColor(BuildContext context) { Color _getBackgroundColor(BuildContext context) {
if (color != null) if (color != null)
return color; return color;
switch (type) { switch (type) {
@ -55,10 +55,10 @@ class Material extends StatelessComponent {
style: Theme.of(context).text.body1, style: Theme.of(context).text.body1,
child: contents child: contents
); );
if (edges[type] != null) { if (_kEdges[type] != null) {
contents = new ClipRRect( contents = new ClipRRect(
xRadius: edges[type], xRadius: _kEdges[type],
yRadius: edges[type], yRadius: _kEdges[type],
child: contents child: contents
); );
} }
@ -69,8 +69,8 @@ class Material extends StatelessComponent {
curve: ease, curve: ease,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
decoration: new BoxDecoration( decoration: new BoxDecoration(
backgroundColor: getBackgroundColor(context), backgroundColor: _getBackgroundColor(context),
borderRadius: edges[type], borderRadius: _kEdges[type],
boxShadow: level == 0 ? null : shadows[level], boxShadow: level == 0 ? null : shadows[level],
shape: type == MaterialType.circle ? Shape.circle : Shape.rectangle shape: type == MaterialType.circle ? Shape.circle : Shape.rectangle
), ),

View File

@ -9,7 +9,7 @@ import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/ink_well.dart'; import 'package:sky/src/widgets/ink_well.dart';
import 'package:sky/src/widgets/material.dart'; import 'package:sky/src/widgets/material.dart';
// Rather than using this class directly, please use FlatButton or RaisedButton. /// Rather than using this class directly, please use FlatButton or RaisedButton.
abstract class MaterialButton extends StatefulComponent { abstract class MaterialButton extends StatefulComponent {
MaterialButton({ MaterialButton({
Key key, Key key,

View File

@ -9,7 +9,7 @@ import 'package:sky/src/widgets/framework.dart';
class MimicableKey { class MimicableKey {
MimicableKey._(this._state); MimicableKey._(this._state);
final MimicableState _state; final _MimicableState _state;
Rect get globalBounds => _state._globalBounds; Rect get globalBounds => _state._globalBounds;
@ -35,10 +35,10 @@ class Mimicable extends StatefulComponent {
final Widget child; final Widget child;
MimicableState createState() => new MimicableState(); _MimicableState createState() => new _MimicableState();
} }
class MimicableState extends State<Mimicable> { class _MimicableState extends State<Mimicable> {
Size _size; Size _size;
bool _beingMimicked = false; bool _beingMimicked = false;

View File

@ -31,7 +31,7 @@ class MixedViewport extends RenderObjectWidget {
final ExtentsUpdateCallback onExtentsUpdate; final ExtentsUpdateCallback onExtentsUpdate;
final InvalidatorAvailableCallback onInvalidatorAvailable; final InvalidatorAvailableCallback onInvalidatorAvailable;
MixedViewportElement createElement() => new MixedViewportElement(this); _MixedViewportElement createElement() => new _MixedViewportElement(this);
// we don't pass constructor arguments to the RenderBlockViewport() because until // we don't pass constructor arguments to the RenderBlockViewport() because until
// we know our children, the constructor arguments we could give have no effect // we know our children, the constructor arguments we could give have no effect
@ -60,8 +60,8 @@ class _ChildKey {
String toString() => "_ChildKey(type: $type, key: $key)"; String toString() => "_ChildKey(type: $type, key: $key)";
} }
class MixedViewportElement extends RenderObjectElement<MixedViewport> { class _MixedViewportElement extends RenderObjectElement<MixedViewport> {
MixedViewportElement(MixedViewport widget) : super(widget) { _MixedViewportElement(MixedViewport widget) : super(widget) {
if (widget.onInvalidatorAvailable != null) if (widget.onInvalidatorAvailable != null)
widget.onInvalidatorAvailable(invalidate); widget.onInvalidatorAvailable(invalidate);
} }

View File

@ -121,8 +121,8 @@ class MenuPosition {
final double left; final double left;
} }
class MenuRoute extends Route { class _MenuRoute extends Route {
MenuRoute({ this.completer, this.position, this.builder, this.level }); _MenuRoute({ this.completer, this.position, this.builder, this.level });
final Completer completer; final Completer completer;
final MenuPosition position; final MenuPosition position;
@ -169,7 +169,7 @@ class MenuRoute extends Route {
Future showMenu({ NavigatorState navigator, MenuPosition position, PopupMenuItemsBuilder builder, int level: 4 }) { Future showMenu({ NavigatorState navigator, MenuPosition position, PopupMenuItemsBuilder builder, int level: 4 }) {
Completer completer = new Completer(); Completer completer = new Completer();
navigator.push(new MenuRoute( navigator.push(new _MenuRoute(
completer: completer, completer: completer,
position: position, position: position,
builder: builder, builder: builder,

View File

@ -31,10 +31,10 @@ abstract class ProgressIndicator extends StatefulComponent {
Widget _buildIndicator(BuildContext context, double performanceValue); Widget _buildIndicator(BuildContext context, double performanceValue);
ProgressIndicatorState createState() => new ProgressIndicatorState(); _ProgressIndicatorState createState() => new _ProgressIndicatorState();
} }
class ProgressIndicatorState extends State<ProgressIndicator> { class _ProgressIndicatorState extends State<ProgressIndicator> {
ValuePerformance<double> _performance; ValuePerformance<double> _performance;

View File

@ -14,7 +14,7 @@ const sky.Color _kDarkOffColor = const sky.Color(0xB2FFFFFF);
typedef RadioValueChanged(Object value); typedef RadioValueChanged(Object value);
class Radio extends StatefulComponent { class Radio extends StatelessComponent {
Radio({ Radio({
Key key, Key key,
this.value, this.value,
@ -28,13 +28,9 @@ class Radio extends StatefulComponent {
final Object groupValue; final Object groupValue;
final RadioValueChanged onChanged; final RadioValueChanged onChanged;
RadioState createState() => new RadioState();
}
class RadioState extends State<Radio> {
Color _getColor(BuildContext context) { Color _getColor(BuildContext context) {
ThemeData themeData = Theme.of(context); ThemeData themeData = Theme.of(context);
if (config.value == config.groupValue) if (value == groupValue)
return themeData.accentColor; return themeData.accentColor;
return themeData.brightness == ThemeBrightness.light ? _kLightOffColor : _kDarkOffColor; return themeData.brightness == ThemeBrightness.light ? _kLightOffColor : _kDarkOffColor;
} }
@ -44,7 +40,7 @@ class RadioState extends State<Radio> {
const double kOuterRadius = kDiameter / 2; const double kOuterRadius = kDiameter / 2;
const double kInnerRadius = 5.0; const double kInnerRadius = 5.0;
return new GestureDetector( return new GestureDetector(
onTap: () => config.onChanged(config.value), onTap: () => onChanged(value),
child: new Container( child: new Container(
margin: const EdgeDims.symmetric(horizontal: 5.0), margin: const EdgeDims.symmetric(horizontal: 5.0),
width: kDiameter, width: kDiameter,
@ -60,7 +56,7 @@ class RadioState extends State<Radio> {
canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kOuterRadius, paint); canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kOuterRadius, paint);
// Draw the inner circle // Draw the inner circle
if (config.value == config.groupValue) { if (value == groupValue) {
paint.setStyle(sky.PaintingStyle.fill); paint.setStyle(sky.PaintingStyle.fill);
canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kInnerRadius, paint); canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kInnerRadius, paint);
} }

View File

@ -22,10 +22,10 @@ class RaisedButton extends MaterialButton {
assert(enabled != null); assert(enabled != null);
} }
RaisedButtonState createState() => new RaisedButtonState(); _RaisedButtonState createState() => new _RaisedButtonState();
} }
class RaisedButtonState extends MaterialButtonState<RaisedButton> { class _RaisedButtonState extends MaterialButtonState<RaisedButton> {
Color getColor(BuildContext context) { Color getColor(BuildContext context) {
if (config.enabled) { if (config.enabled) {
switch (Theme.of(context).brightness) { switch (Theme.of(context).brightness) {

View File

@ -9,7 +9,7 @@ import 'package:sky/rendering.dart';
import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/framework.dart';
// Slots are painted in this order and hit tested in reverse of this order // Slots are painted in this order and hit tested in reverse of this order
enum ScaffoldSlots { enum _ScaffoldSlots {
body, body,
statusBar, statusBar,
toolbar, toolbar,
@ -18,9 +18,9 @@ enum ScaffoldSlots {
drawer drawer
} }
class RenderScaffold extends RenderBox { class _RenderScaffold extends RenderBox {
RenderScaffold({ _RenderScaffold({
RenderBox body, RenderBox body,
RenderBox statusBar, RenderBox statusBar,
RenderBox toolbar, RenderBox toolbar,
@ -28,17 +28,17 @@ class RenderScaffold extends RenderBox {
RenderBox floatingActionButton, RenderBox floatingActionButton,
RenderBox drawer RenderBox drawer
}) { }) {
this[ScaffoldSlots.body] = body; this[_ScaffoldSlots.body] = body;
this[ScaffoldSlots.statusBar] = statusBar; this[_ScaffoldSlots.statusBar] = statusBar;
this[ScaffoldSlots.toolbar] = toolbar; this[_ScaffoldSlots.toolbar] = toolbar;
this[ScaffoldSlots.snackBar] = snackBar; this[_ScaffoldSlots.snackBar] = snackBar;
this[ScaffoldSlots.floatingActionButton] = floatingActionButton; this[_ScaffoldSlots.floatingActionButton] = floatingActionButton;
this[ScaffoldSlots.drawer] = drawer; this[_ScaffoldSlots.drawer] = drawer;
} }
Map<ScaffoldSlots, RenderBox> _slots = new Map<ScaffoldSlots, RenderBox>(); Map<_ScaffoldSlots, RenderBox> _slots = new Map<_ScaffoldSlots, RenderBox>();
RenderBox operator[] (ScaffoldSlots slot) => _slots[slot]; RenderBox operator[] (_ScaffoldSlots slot) => _slots[slot];
void operator[]= (ScaffoldSlots slot, RenderBox value) { void operator[]= (_ScaffoldSlots slot, RenderBox value) {
RenderBox old = _slots[slot]; RenderBox old = _slots[slot];
if (old == value) if (old == value)
return; return;
@ -54,7 +54,7 @@ class RenderScaffold extends RenderBox {
} }
void attachChildren() { void attachChildren() {
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
RenderBox box = _slots[slot]; RenderBox box = _slots[slot];
if (box != null) if (box != null)
box.attach(); box.attach();
@ -62,7 +62,7 @@ class RenderScaffold extends RenderBox {
} }
void detachChildren() { void detachChildren() {
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
RenderBox box = _slots[slot]; RenderBox box = _slots[slot];
if (box != null) if (box != null)
box.detach(); box.detach();
@ -70,16 +70,16 @@ class RenderScaffold extends RenderBox {
} }
void visitChildren(RenderObjectVisitor visitor) { void visitChildren(RenderObjectVisitor visitor) {
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
RenderBox box = _slots[slot]; RenderBox box = _slots[slot];
if (box != null) if (box != null)
visitor(box); visitor(box);
} }
} }
ScaffoldSlots remove(RenderBox child) { _ScaffoldSlots remove(RenderBox child) {
assert(child != null); assert(child != null);
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
if (_slots[slot] == child) { if (_slots[slot] == child) {
this[slot] = null; this[slot] = null;
return slot; return slot;
@ -103,15 +103,15 @@ class RenderScaffold extends RenderBox {
double bodyHeight = size.height; double bodyHeight = size.height;
double bodyPosition = 0.0; double bodyPosition = 0.0;
double fabOffset = 0.0; double fabOffset = 0.0;
if (_slots[ScaffoldSlots.statusBar] != null) { if (_slots[_ScaffoldSlots.statusBar] != null) {
RenderBox statusBar = _slots[ScaffoldSlots.statusBar]; RenderBox statusBar = _slots[_ScaffoldSlots.statusBar];
statusBar.layout(new BoxConstraints.tight(new Size(size.width, kStatusBarHeight))); statusBar.layout(new BoxConstraints.tight(new Size(size.width, kStatusBarHeight)));
assert(statusBar.parentData is BoxParentData); assert(statusBar.parentData is BoxParentData);
statusBar.parentData.position = new Point(0.0, size.height - kStatusBarHeight); statusBar.parentData.position = new Point(0.0, size.height - kStatusBarHeight);
bodyHeight -= kStatusBarHeight; bodyHeight -= kStatusBarHeight;
} }
if (_slots[ScaffoldSlots.toolbar] != null) { if (_slots[_ScaffoldSlots.toolbar] != null) {
RenderBox toolbar = _slots[ScaffoldSlots.toolbar]; RenderBox toolbar = _slots[_ScaffoldSlots.toolbar];
double toolbarHeight = kToolBarHeight + sky.view.paddingTop; double toolbarHeight = kToolBarHeight + sky.view.paddingTop;
toolbar.layout(new BoxConstraints.tight(new Size(size.width, toolbarHeight))); toolbar.layout(new BoxConstraints.tight(new Size(size.width, toolbarHeight)));
assert(toolbar.parentData is BoxParentData); assert(toolbar.parentData is BoxParentData);
@ -119,14 +119,14 @@ class RenderScaffold extends RenderBox {
bodyPosition += toolbarHeight; bodyPosition += toolbarHeight;
bodyHeight -= toolbarHeight; bodyHeight -= toolbarHeight;
} }
if (_slots[ScaffoldSlots.body] != null) { if (_slots[_ScaffoldSlots.body] != null) {
RenderBox body = _slots[ScaffoldSlots.body]; RenderBox body = _slots[_ScaffoldSlots.body];
body.layout(new BoxConstraints.tight(new Size(size.width, bodyHeight))); body.layout(new BoxConstraints.tight(new Size(size.width, bodyHeight)));
assert(body.parentData is BoxParentData); assert(body.parentData is BoxParentData);
body.parentData.position = new Point(0.0, bodyPosition); body.parentData.position = new Point(0.0, bodyPosition);
} }
if (_slots[ScaffoldSlots.snackBar] != null) { if (_slots[_ScaffoldSlots.snackBar] != null) {
RenderBox snackBar = _slots[ScaffoldSlots.snackBar]; RenderBox snackBar = _slots[_ScaffoldSlots.snackBar];
// TODO(jackson): On tablet/desktop, minWidth = 288, maxWidth = 568 // TODO(jackson): On tablet/desktop, minWidth = 288, maxWidth = 568
snackBar.layout( snackBar.layout(
new BoxConstraints(minWidth: size.width, maxWidth: size.width, minHeight: 0.0, maxHeight: bodyHeight), new BoxConstraints(minWidth: size.width, maxWidth: size.width, minHeight: 0.0, maxHeight: bodyHeight),
@ -136,15 +136,15 @@ class RenderScaffold extends RenderBox {
snackBar.parentData.position = new Point(0.0, bodyPosition + bodyHeight - snackBar.size.height); snackBar.parentData.position = new Point(0.0, bodyPosition + bodyHeight - snackBar.size.height);
fabOffset += snackBar.size.height; fabOffset += snackBar.size.height;
} }
if (_slots[ScaffoldSlots.floatingActionButton] != null) { if (_slots[_ScaffoldSlots.floatingActionButton] != null) {
RenderBox floatingActionButton = _slots[ScaffoldSlots.floatingActionButton]; RenderBox floatingActionButton = _slots[_ScaffoldSlots.floatingActionButton];
Size area = new Size(size.width - kButtonX, size.height - kButtonY); Size area = new Size(size.width - kButtonX, size.height - kButtonY);
floatingActionButton.layout(new BoxConstraints.loose(area), parentUsesSize: true); floatingActionButton.layout(new BoxConstraints.loose(area), parentUsesSize: true);
assert(floatingActionButton.parentData is BoxParentData); assert(floatingActionButton.parentData is BoxParentData);
floatingActionButton.parentData.position = (area - floatingActionButton.size).toPoint() + new Offset(0.0, -fabOffset); floatingActionButton.parentData.position = (area - floatingActionButton.size).toPoint() + new Offset(0.0, -fabOffset);
} }
if (_slots[ScaffoldSlots.drawer] != null) { if (_slots[_ScaffoldSlots.drawer] != null) {
RenderBox drawer = _slots[ScaffoldSlots.drawer]; RenderBox drawer = _slots[_ScaffoldSlots.drawer];
drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: size.width, minHeight: size.height, maxHeight: size.height)); drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: size.width, minHeight: size.height, maxHeight: size.height));
assert(drawer.parentData is BoxParentData); assert(drawer.parentData is BoxParentData);
drawer.parentData.position = Point.origin; drawer.parentData.position = Point.origin;
@ -152,7 +152,7 @@ class RenderScaffold extends RenderBox {
} }
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
RenderBox box = _slots[slot]; RenderBox box = _slots[slot];
if (box != null) { if (box != null) {
assert(box.parentData is BoxParentData); assert(box.parentData is BoxParentData);
@ -162,7 +162,7 @@ class RenderScaffold extends RenderBox {
} }
void hitTestChildren(HitTestResult result, { Point position }) { void hitTestChildren(HitTestResult result, { Point position }) {
for (ScaffoldSlots slot in ScaffoldSlots.values.reversed) { for (_ScaffoldSlots slot in _ScaffoldSlots.values.reversed) {
RenderBox box = _slots[slot]; RenderBox box = _slots[slot];
if (box != null) { if (box != null) {
assert(box.parentData is BoxParentData); assert(box.parentData is BoxParentData);
@ -187,30 +187,30 @@ class Scaffold extends RenderObjectWidget {
Widget floatingActionButton, Widget floatingActionButton,
Widget drawer Widget drawer
}) : super(key: key) { }) : super(key: key) {
_children[ScaffoldSlots.body] = body; _children[_ScaffoldSlots.body] = body;
_children[ScaffoldSlots.statusBar] = statusBar; _children[_ScaffoldSlots.statusBar] = statusBar;
_children[ScaffoldSlots.toolbar] = toolbar; _children[_ScaffoldSlots.toolbar] = toolbar;
_children[ScaffoldSlots.snackBar] = snackBar; _children[_ScaffoldSlots.snackBar] = snackBar;
_children[ScaffoldSlots.floatingActionButton] = floatingActionButton; _children[_ScaffoldSlots.floatingActionButton] = floatingActionButton;
_children[ScaffoldSlots.drawer] = drawer; _children[_ScaffoldSlots.drawer] = drawer;
} }
final Map<ScaffoldSlots, Widget> _children = new Map<ScaffoldSlots, Widget>(); final Map<_ScaffoldSlots, Widget> _children = new Map<_ScaffoldSlots, Widget>();
RenderScaffold createRenderObject() => new RenderScaffold(); _RenderScaffold createRenderObject() => new _RenderScaffold();
ScaffoldElement createElement() => new ScaffoldElement(this); _ScaffoldElement createElement() => new _ScaffoldElement(this);
} }
class ScaffoldElement extends RenderObjectElement<Scaffold> { class _ScaffoldElement extends RenderObjectElement<Scaffold> {
ScaffoldElement(Scaffold widget) : super(widget); _ScaffoldElement(Scaffold widget) : super(widget);
Map<ScaffoldSlots, Element> _children; Map<_ScaffoldSlots, Element> _children;
RenderScaffold get renderObject => super.renderObject; _RenderScaffold get renderObject => super.renderObject;
void visitChildren(ElementVisitor visitor) { void visitChildren(ElementVisitor visitor) {
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
Element element = _children[slot]; Element element = _children[slot];
if (element != null) if (element != null)
visitor(element); visitor(element);
@ -219,8 +219,8 @@ class ScaffoldElement extends RenderObjectElement<Scaffold> {
void mount(Element parent, dynamic newSlot) { void mount(Element parent, dynamic newSlot) {
super.mount(parent, newSlot); super.mount(parent, newSlot);
_children = new Map<ScaffoldSlots, Element>(); _children = new Map<_ScaffoldSlots, Element>();
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
Element newChild = widget._children[slot]?.createElement(); Element newChild = widget._children[slot]?.createElement();
_children[slot] = newChild; _children[slot] = newChild;
newChild?.mount(this, slot); newChild?.mount(this, slot);
@ -230,13 +230,13 @@ class ScaffoldElement extends RenderObjectElement<Scaffold> {
void update(Scaffold newWidget) { void update(Scaffold newWidget) {
super.update(newWidget); super.update(newWidget);
assert(widget == newWidget); assert(widget == newWidget);
for (ScaffoldSlots slot in ScaffoldSlots.values) { for (_ScaffoldSlots slot in _ScaffoldSlots.values) {
_children[slot] = updateChild(_children[slot], widget._children[slot], slot); _children[slot] = updateChild(_children[slot], widget._children[slot], slot);
assert((_children[slot] == null) == (widget._children[slot] == null)); assert((_children[slot] == null) == (widget._children[slot] == null));
} }
} }
void insertChildRenderObject(RenderObject child, ScaffoldSlots slot) { void insertChildRenderObject(RenderObject child, _ScaffoldSlots slot) {
renderObject[slot] = child; renderObject[slot] = child;
} }

View File

@ -15,7 +15,6 @@ import 'package:sky/src/widgets/placeholder.dart';
import 'package:sky/src/widgets/theme.dart'; import 'package:sky/src/widgets/theme.dart';
import 'package:sky/src/widgets/transitions.dart'; import 'package:sky/src/widgets/transitions.dart';
const Duration _kSlideInDuration = const Duration(milliseconds: 200);
const double _kSnackHeight = 52.0; const double _kSnackHeight = 52.0;
const double _kSideMargins = 24.0; const double _kSideMargins = 24.0;
const double _kVerticalPadding = 14.0; const double _kVerticalPadding = 14.0;
@ -108,7 +107,7 @@ class _SnackBarRoute extends Route {
bool get hasContent => false; bool get hasContent => false;
bool get ephemeral => true; bool get ephemeral => true;
bool get modal => false; bool get modal => false;
Duration get transitionDuration => _kSlideInDuration; Duration get transitionDuration => const Duration(milliseconds: 200);
Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) => null; Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) => null;
} }

View File

@ -19,8 +19,8 @@ import 'package:sky/src/widgets/scrollable.dart';
import 'package:sky/src/widgets/theme.dart'; import 'package:sky/src/widgets/theme.dart';
import 'package:sky/src/widgets/transitions.dart'; import 'package:sky/src/widgets/transitions.dart';
typedef void SelectedIndexChanged(int selectedIndex); typedef void TabSelectedIndexChanged(int selectedIndex);
typedef void LayoutChanged(Size size, List<double> widths); typedef void TabLayoutChanged(Size size, List<double> widths);
// See https://www.google.com/design/spec/components/tabs.html#tabs-specs // See https://www.google.com/design/spec/components/tabs.html#tabs-specs
const double _kTabHeight = 46.0; const double _kTabHeight = 46.0;
@ -33,14 +33,14 @@ const int _kTabIconSize = 24;
const double _kTabBarScrollDrag = 0.025; const double _kTabBarScrollDrag = 0.025;
const Duration _kTabBarScroll = const Duration(milliseconds: 200); const Duration _kTabBarScroll = const Duration(milliseconds: 200);
class TabBarParentData extends BoxParentData with class _TabBarParentData extends BoxParentData with
ContainerParentDataMixin<RenderBox> { } ContainerParentDataMixin<RenderBox> { }
class RenderTabBar extends RenderBox with class _RenderTabBar extends RenderBox with
ContainerRenderObjectMixin<RenderBox, TabBarParentData>, ContainerRenderObjectMixin<RenderBox, _TabBarParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> { RenderBoxContainerDefaultsMixin<RenderBox, _TabBarParentData> {
RenderTabBar(this.onLayoutChanged); _RenderTabBar(this.onLayoutChanged);
int _selectedIndex; int _selectedIndex;
int get selectedIndex => _selectedIndex; int get selectedIndex => _selectedIndex;
@ -97,8 +97,8 @@ class RenderTabBar extends RenderBox with
} }
void setupParentData(RenderBox child) { void setupParentData(RenderBox child) {
if (child.parentData is! TabBarParentData) if (child.parentData is! _TabBarParentData)
child.parentData = new TabBarParentData(); child.parentData = new _TabBarParentData();
} }
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
@ -109,7 +109,7 @@ class RenderTabBar extends RenderBox with
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints)); maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints));
assert(child.parentData is TabBarParentData); assert(child.parentData is _TabBarParentData);
child = child.parentData.nextSibling; child = child.parentData.nextSibling;
} }
double width = isScrollable ? maxWidth : maxWidth * childCount; double width = isScrollable ? maxWidth : maxWidth * childCount;
@ -124,7 +124,7 @@ class RenderTabBar extends RenderBox with
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints)); maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints));
assert(child.parentData is TabBarParentData); assert(child.parentData is _TabBarParentData);
child = child.parentData.nextSibling; child = child.parentData.nextSibling;
} }
double width = isScrollable ? maxWidth : maxWidth * childCount; double width = isScrollable ? maxWidth : maxWidth * childCount;
@ -148,7 +148,7 @@ class RenderTabBar extends RenderBox with
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
child.layout(tabConstraints); child.layout(tabConstraints);
assert(child.parentData is TabBarParentData); assert(child.parentData is _TabBarParentData);
child.parentData.position = new Point(x, 0.0); child.parentData.position = new Point(x, 0.0);
x += tabWidth; x += tabWidth;
child = child.parentData.nextSibling; child = child.parentData.nextSibling;
@ -166,7 +166,7 @@ class RenderTabBar extends RenderBox with
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
child.layout(tabConstraints, parentUsesSize: true); child.layout(tabConstraints, parentUsesSize: true);
assert(child.parentData is TabBarParentData); assert(child.parentData is _TabBarParentData);
child.parentData.position = new Point(x, 0.0); child.parentData.position = new Point(x, 0.0);
x += child.size.width; x += child.size.width;
child = child.parentData.nextSibling; child = child.parentData.nextSibling;
@ -176,7 +176,7 @@ class RenderTabBar extends RenderBox with
Size layoutSize; Size layoutSize;
List<double> layoutWidths; List<double> layoutWidths;
LayoutChanged onLayoutChanged; TabLayoutChanged onLayoutChanged;
void reportLayoutChangedIfNeeded() { void reportLayoutChangedIfNeeded() {
assert(onLayoutChanged != null); assert(onLayoutChanged != null);
@ -250,7 +250,7 @@ class RenderTabBar extends RenderBox with
int index = 0; int index = 0;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
assert(child.parentData is TabBarParentData); assert(child.parentData is _TabBarParentData);
context.paintChild(child, child.parentData.position + offset); context.paintChild(child, child.parentData.position + offset);
if (index++ == selectedIndex) if (index++ == selectedIndex)
_paintIndicator(context.canvas, child, offset); _paintIndicator(context.canvas, child, offset);
@ -278,15 +278,15 @@ class _TabBarWrapper extends MultiChildRenderObjectWidget {
final Rect indicatorRect; final Rect indicatorRect;
final bool textAndIcons; final bool textAndIcons;
final bool isScrollable; final bool isScrollable;
final LayoutChanged onLayoutChanged; final TabLayoutChanged onLayoutChanged;
RenderTabBar createRenderObject() { _RenderTabBar createRenderObject() {
RenderTabBar result = new RenderTabBar(onLayoutChanged); _RenderTabBar result = new _RenderTabBar(onLayoutChanged);
updateRenderObject(result, null); updateRenderObject(result, null);
return result; return result;
} }
void updateRenderObject(RenderTabBar renderObject, _TabBarWrapper oldWidget) { void updateRenderObject(_RenderTabBar renderObject, _TabBarWrapper oldWidget) {
renderObject.selectedIndex = selectedIndex; renderObject.selectedIndex = selectedIndex;
renderObject.backgroundColor = backgroundColor; renderObject.backgroundColor = backgroundColor;
renderObject.indicatorColor = indicatorColor; renderObject.indicatorColor = indicatorColor;
@ -399,13 +399,13 @@ class TabBar extends Scrollable {
final Iterable<TabLabel> labels; final Iterable<TabLabel> labels;
final int selectedIndex; final int selectedIndex;
final SelectedIndexChanged onChanged; final TabSelectedIndexChanged onChanged;
final bool isScrollable; final bool isScrollable;
TabBarState createState() => new TabBarState(); _TabBarState createState() => new _TabBarState();
} }
class TabBarState extends ScrollableState<TabBar> { class _TabBarState extends ScrollableState<TabBar> {
void initState() { void initState() {
super.initState(); super.initState();
_indicatorAnimation = new ValuePerformance<Rect>() _indicatorAnimation = new ValuePerformance<Rect>()
@ -598,7 +598,7 @@ class TabNavigator extends StatelessComponent {
final List<TabNavigatorView> views; final List<TabNavigatorView> views;
final int selectedIndex; final int selectedIndex;
final SelectedIndexChanged onChanged; final TabSelectedIndexChanged onChanged;
final bool isScrollable; final bool isScrollable;
void _handleSelectedIndexChanged(int tabIndex) { void _handleSelectedIndexChanged(int tabIndex) {

View File

@ -21,10 +21,10 @@ abstract class TransitionComponent extends StatefulComponent {
Widget build(BuildContext context); Widget build(BuildContext context);
TransitionState createState() => new TransitionState(); _TransitionState createState() => new _TransitionState();
} }
class TransitionState extends State<TransitionComponent> { class _TransitionState extends State<TransitionComponent> {
void initState() { void initState() {
super.initState(); super.initState();
config.performance.addListener(_performanceChanged); config.performance.addListener(_performanceChanged);