浏览代码

Merge branch 'master' of gitlab.cds.internal.unity3d.com:upm-packages/ui-widgets/com.unity.uiwidgets into material

/main
xingwei.zhu 6 年前
当前提交
e4f3e3a4
共有 34 个文件被更改,包括 3975 次插入10 次删除
  1. 2
      Runtime/material/button_theme.cs
  2. 6
      Runtime/material/material_localizations.cs
  3. 15
      Runtime/material/theme_data.cs
  4. 65
      Runtime/rendering/stack.cs
  5. 12
      Runtime/ui/painting/path.cs
  6. 31
      Runtime/widgets/basic.cs
  7. 2
      Runtime/widgets/framework.cs
  8. 49
      Runtime/widgets/implicit_animations.cs
  9. 4
      Runtime/widgets/scroll_configuration.cs
  10. 8
      Tests/Editor/Widgets.cs
  11. 747
      Runtime/material/dropdown.cs
  12. 3
      Runtime/material/dropdown.cs.meta
  13. 368
      Runtime/material/input_border.cs
  14. 3
      Runtime/material/input_border.cs.meta
  15. 1001
      Runtime/material/input_decorator.cs
  16. 3
      Runtime/material/input_decorator.cs.meta
  17. 460
      Runtime/material/outline_button.cs
  18. 3
      Runtime/material/outline_button.cs.meta
  19. 530
      Runtime/material/progress_indicator.cs
  20. 3
      Runtime/material/progress_indicator.cs.meta
  21. 248
      Runtime/widgets/form.cs
  22. 3
      Runtime/widgets/form.cs.meta
  23. 69
      Runtime/widgets/will_pop_scope.cs
  24. 3
      Runtime/widgets/will_pop_scope.cs.meta
  25. 8
      Tests/Editor/demo_charts.meta
  26. 149
      Tests/Editor/demo_charts/bar.cs
  27. 11
      Tests/Editor/demo_charts/bar.cs.meta
  28. 38
      Tests/Editor/demo_charts/color_palette.cs
  29. 11
      Tests/Editor/demo_charts/color_palette.cs.meta
  30. 67
      Tests/Editor/demo_charts/main.cs
  31. 11
      Tests/Editor/demo_charts/main.cs.meta
  32. 41
      Tests/Editor/demo_charts/tween.cs
  33. 11
      Tests/Editor/demo_charts/tween.cs.meta

2
Runtime/material/button_theme.cs


}
Color getDisabledTextColor(MaterialButton button) {
public Color getDisabledTextColor(MaterialButton button) {
if (button.disabledTextColor != null) {
return button.disabledTextColor;
}

6
Runtime/material/material_localizations.cs


public abstract List<string> narrowWeekdays { get; }
public abstract int firstDayOfWeekIndex { get; }
public abstract string modalBarrierDismissLabel { get; }
public static MaterialLocalizations of(BuildContext context) {
return Localizations.of<MaterialLocalizations>(context, typeof(MaterialLocalizations));

public override string postMeridiemAbbreviation {
get { return "PM"; }
}
public override string modalBarrierDismissLabel {
get { return "Dismiss"; }
}
public override ScriptCategory scriptCategory {

15
Runtime/material/theme_data.cs


TextTheme textTheme = null,
TextTheme primaryTextTheme = null,
TextTheme accentTextTheme = null,
InputDecorationTheme inputDecorationTheme = null,
IconThemeData iconTheme = null,
IconThemeData primaryIconTheme = null,
IconThemeData accentIconTheme = null,

indicatorColor = indicatorColor ?? (accentColor == primaryColor ? Colors.white : accentColor);
hintColor = hintColor ?? (isDark ? new Color(0x80FFFFFF) : new Color(0x8A000000));
errorColor = errorColor ?? Colors.red[700];
inputDecorationTheme = inputDecorationTheme ?? new InputDecorationTheme();
pageTransitionsTheme = pageTransitionsTheme ?? new PageTransitionsTheme();
primaryIconTheme = primaryIconTheme ??
(primaryIsDark

this.textTheme = textTheme;
this.primaryTextTheme = primaryTextTheme;
this.accentTextTheme = accentTextTheme;
this.inputDecorationTheme = inputDecorationTheme;
this.iconTheme = iconTheme;
this.primaryIconTheme = primaryIconTheme;
this.accentIconTheme = accentIconTheme;

TextTheme textTheme = null,
TextTheme primaryTextTheme = null,
TextTheme accentTextTheme = null,
InputDecorationTheme inputDecorationTheme = null,
IconThemeData iconTheme = null,
IconThemeData primaryIconTheme = null,
IconThemeData accentIconTheme = null,

D.assert(textTheme != null);
D.assert(primaryTextTheme != null);
D.assert(accentTextTheme != null);
D.assert(inputDecorationTheme != null);
D.assert(iconTheme != null);
D.assert(primaryIconTheme != null);
D.assert(accentIconTheme != null);

textTheme: textTheme,
primaryTextTheme: primaryTextTheme,
accentTextTheme: accentTextTheme,
inputDecorationTheme: inputDecorationTheme,
iconTheme: iconTheme,
primaryIconTheme: primaryIconTheme,
accentIconTheme: accentIconTheme,

public readonly TextTheme accentTextTheme;
public readonly InputDecorationTheme inputDecorationTheme;
public readonly IconThemeData iconTheme;
public readonly IconThemeData primaryIconTheme;

TextTheme textTheme = null,
TextTheme primaryTextTheme = null,
TextTheme accentTextTheme = null,
InputDecorationTheme inputDecorationTheme = null,
IconThemeData iconTheme = null,
IconThemeData primaryIconTheme = null,
IconThemeData accentIconTheme = null,

textTheme: textTheme ?? this.textTheme,
primaryTextTheme: primaryTextTheme ?? this.primaryTextTheme,
accentTextTheme: accentTextTheme ?? this.accentTextTheme,
inputDecorationTheme: this.inputDecorationTheme ?? this.inputDecorationTheme,
iconTheme: iconTheme ?? this.iconTheme,
primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme,
accentIconTheme: accentIconTheme ?? this.accentIconTheme,

textTheme: TextTheme.lerp(a.textTheme, b.textTheme, t),
primaryTextTheme: TextTheme.lerp(a.primaryTextTheme, b.primaryTextTheme, t),
accentTextTheme: TextTheme.lerp(a.accentTextTheme, b.accentTextTheme, t),
inputDecorationTheme: t < 0.5f ? a.inputDecorationTheme : b.inputDecorationTheme,
iconTheme: IconThemeData.lerp(a.iconTheme, b.iconTheme, t),
primaryIconTheme: IconThemeData.lerp(a.primaryIconTheme, b.primaryIconTheme, t),
accentIconTheme: IconThemeData.lerp(a.accentIconTheme, b.accentIconTheme, t),

other.textTheme == this.textTheme &&
other.primaryTextTheme == this.primaryTextTheme &&
other.accentTextTheme == this.accentTextTheme &&
other.inputDecorationTheme == this.inputDecorationTheme &&
other.toggleableActiveColor == this.toggleableActiveColor &&
other.iconTheme == this.iconTheme &&
other.primaryIconTheme == this.primaryIconTheme &&

hashCode = (hashCode * 397) ^ this.textTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.primaryTextTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.accentTextTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.inputDecorationTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.iconTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.primaryIconTheme.GetHashCode();
hashCode = (hashCode * 397) ^ this.accentIconTheme.GetHashCode();

properties.add(new DiagnosticsProperty<TextTheme>("textTheme", this.textTheme));
properties.add(new DiagnosticsProperty<TextTheme>("primaryTextTheme", this.primaryTextTheme));
properties.add(new DiagnosticsProperty<TextTheme>("accentTextTheme", this.accentTextTheme));
properties.add(new DiagnosticsProperty<InputDecorationTheme>("inputDecorationTheme", this.inputDecorationTheme));
properties.add(new DiagnosticsProperty<Color>("toggleableActiveColor", this.toggleableActiveColor,
defaultValue: defaultData.toggleableActiveColor));
properties.add(new DiagnosticsProperty<IconThemeData>("iconTheme", this.iconTheme));

65
Runtime/rendering/stack.cs


return this.defaultHitTestChildren(result, position: position);
}
public void paintStack(PaintingContext context, Offset offset) {
public virtual void paintStack(PaintingContext context, Offset offset) {
this.defaultPaint(context, offset);
}

properties.add(new DiagnosticsProperty<Alignment>("alignment", this.alignment));
properties.add(new EnumProperty<StackFit>("fit", this.fit));
properties.add(new EnumProperty<Overflow>("overflow", this.overflow));
}
}
class RenderIndexedStack : RenderStack {
public RenderIndexedStack(
List<RenderBox> children = null,
Alignment alignment = null,
int? index = 0
) : base(fit: null, overflow: null, children: children, alignment: alignment ?? Alignment.topLeft) {
this._index = index;
}
public int? index {
get { return this._index; }
set {
if (this._index != value) {
this._index = value;
this.markNeedsLayout();
}
}
}
int? _index;
RenderBox _childAtIndex() {
D.assert(this.index != null);
RenderBox child = this.firstChild;
int i = 0;
while (child != null && i < this.index) {
StackParentData childParentData = (StackParentData) child.parentData;
child = childParentData.nextSibling;
i += 1;
}
D.assert(i == this.index);
D.assert(child != null);
return child;
}
protected override bool hitTestChildren(HitTestResult result, Offset position) {
if (this.firstChild == null || this.index == null) {
return false;
}
D.assert(position != null);
RenderBox child = this._childAtIndex();
StackParentData childParentData = (StackParentData) child.parentData;
return child.hitTest(result, position: position - childParentData.offset);
}
public override void paintStack(PaintingContext context, Offset offset) {
if (this.firstChild == null || this.index == null) {
return;
}
RenderBox child = this._childAtIndex();
StackParentData childParentData = (StackParentData) child.parentData;
context.paintChild(child, childParentData.offset + offset);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new IntProperty("index", this.index));
}
}
}

12
Runtime/ui/painting/path.cs


this._cache = null;
}
public void relativeMoveTo(float x, float y) {
var x0 = this._commandx;
var y0 = this._commandy;
this._appendCommands(new[] {
(float) PathCommand.moveTo,
x + x0, y + y0,
});
}
}
}
public void lineTo(float x, float y) {
this._appendCommands(new[] {

31
Runtime/widgets/basic.cs


}
}
class IndexedStack : Stack {
public IndexedStack(
Key key = null,
Alignment alignment = null,
StackFit sizing = StackFit.loose,
int index = 0,
List<Widget> children = null
) : base(key: key, alignment: alignment ?? Alignment.topLeft, fit: sizing, children: children) {
this.index = index;
}
public readonly int index;
public override RenderObject createRenderObject(BuildContext context) {
return new RenderIndexedStack(
index: this.index,
alignment: this.alignment
);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
RenderIndexedStack renderIndexedStack = renderObject as RenderIndexedStack;
renderIndexedStack.index = this.index;
renderIndexedStack.alignment = this.alignment;
}
}
public class Positioned : ParentDataWidget<Stack> {
public Positioned(Widget child, Key key = null, float? left = null, float? top = null,
float? right = null, float? bottom = null, float? width = null, float? height = null) :

public static List<Widget> ensureUniqueKeysForList(IEnumerable<Widget> items, int baseIndex = 0) {
if (items == null) {
return null;
itemsWithUniqueKeys.Add(KeyedSubtree.wrap(item, itemIndex));
itemsWithUniqueKeys.Add(wrap(item, itemIndex));
itemIndex += 1;
}

2
Runtime/widgets/framework.cs


}
public abstract class StatefulWidget : Widget {
protected StatefulWidget(Key key) : base(key: key) {
protected StatefulWidget(Key key = null) : base(key: key) {
}
public override Element createElement() {

49
Runtime/widgets/implicit_animations.cs


}
}
public class AnimatedOpacity : ImplicitlyAnimatedWidget {
public AnimatedOpacity(
Key key = null,
Widget child = null,
float? opacity = null,
Curve curve = null,
TimeSpan? duration = null
) :
base(key: key, curve: curve ?? Curves.linear, duration: duration) {
D.assert(opacity != null && opacity >= 0.0 && opacity <= 1.0);
this.child = child;
this.opacity = opacity ?? 1.0f;
}
public readonly Widget child;
public readonly float opacity;
public override State createState() {
return new _AnimatedOpacityState();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new FloatProperty("opacity", this.opacity));
}
}
class _AnimatedOpacityState : ImplicitlyAnimatedWidgetState<AnimatedOpacity> {
FloatTween _opacity;
Animation<float> _opacityAnimation;
protected override void forEachTween(TweenVisitor visitor) {
this._opacity = (FloatTween) visitor.visit(this, this._opacity, this.widget.opacity,
(float value) => new FloatTween(begin: value, end: 1.0f));
}
protected override void didUpdateTweens() {
this._opacityAnimation = this.animation.drive(this._opacity);
}
public override Widget build(BuildContext context) {
return new FadeTransition(
opacity: this._opacityAnimation,
child: this.widget.child
);
}
}
public class AnimatedDefaultTextStyle : ImplicitlyAnimatedWidget {
public AnimatedDefaultTextStyle(
Key key = null,

4
Runtime/widgets/scroll_configuration.cs


namespace Unity.UIWidgets.widgets {
public class ScrollBehavior {
public Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
public virtual Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
public ScrollPhysics getScrollPhysics(BuildContext context) {
public virtual ScrollPhysics getScrollPhysics(BuildContext context) {
return new BouncingScrollPhysics();
}

8
Tests/Editor/Widgets.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.Tests.demo_charts;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.editor;
using Unity.UIWidgets.foundation;

this.eventsPage,
this.asPage,
this.stack,
this.mouseHover
this.mouseHover,
this.charts
};
this._optionStrings = this._options.Select(x => x.Method.Name).ToArray();
this._selected = 0;

Widget mouseHover() {
return new MouseHoverWidget();
}
Widget charts() {
return new ChartPage();
}
}

747
Runtime/material/dropdown.cs


using System;
using System.Collections.Generic;
using System.Linq;
using RSG;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.material {
class DropdownConstants {
public static readonly TimeSpan _kDropdownMenuDuration = new TimeSpan(0, 0, 0, 0, 300);
public const float _kMenuItemHeight = 48.0f;
public const float _kDenseButtonHeight = 24.0f;
public static readonly EdgeInsets _kMenuItemPadding = EdgeInsets.symmetric(horizontal: 16.0f);
public static readonly EdgeInsets _kAlignedButtonPadding = EdgeInsets.only(left: 16.0f, right: 4.0f);
public static readonly EdgeInsets _kUnalignedButtonPadding = EdgeInsets.zero;
public static readonly EdgeInsets _kAlignedMenuMargin = EdgeInsets.zero;
public static readonly EdgeInsets _kUnalignedMenuMargin = EdgeInsets.only(left: 16.0f, right: 24.0f);
}
class _DropdownMenuPainter : AbstractCustomPainter {
public _DropdownMenuPainter(
Color color = null,
int? elevation = null,
int? selectedIndex = null,
Animation<float> resize = null
) : base(repaint: resize) {
D.assert(elevation != null);
this._painter = new BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(2.0f),
boxShadow: ShadowConstants.kElevationToShadow[elevation ?? 0]
).createBoxPainter();
this.color = color;
this.elevation = elevation;
this.selectedIndex = selectedIndex;
this.resize = resize;
}
public readonly Color color;
public readonly int? elevation;
public readonly int? selectedIndex;
public readonly Animation<float> resize;
public readonly BoxPainter _painter;
public override void paint(Canvas canvas, Size size) {
float selectedItemOffset = this.selectedIndex ?? 0 * DropdownConstants._kMenuItemHeight +
Constants.kMaterialListPadding.top;
FloatTween top = new FloatTween(
begin: selectedItemOffset.clamp(0.0f, size.height - DropdownConstants._kMenuItemHeight),
end: 0.0f
);
FloatTween bottom = new FloatTween(
begin: (top.begin + DropdownConstants._kMenuItemHeight).clamp(DropdownConstants._kMenuItemHeight,
size.height),
end: size.height
);
Rect rect = Rect.fromLTRB(0.0f, top.evaluate(this.resize), size.width, bottom.evaluate(this.resize));
this._painter.paint(canvas, rect.topLeft, new ImageConfiguration(size: rect.size));
}
public override bool shouldRepaint(CustomPainter painter) {
_DropdownMenuPainter oldPainter = painter as _DropdownMenuPainter;
return oldPainter.color != this.color
|| oldPainter.elevation != this.elevation
|| oldPainter.selectedIndex != this.selectedIndex
|| oldPainter.resize != this.resize;
}
}
class _DropdownScrollBehavior : ScrollBehavior {
public _DropdownScrollBehavior() {
}
public override Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
return child;
}
public override ScrollPhysics getScrollPhysics(BuildContext context) {
return new ClampingScrollPhysics();
}
}
class _DropdownMenu<T> : StatefulWidget where T : class {
public _DropdownMenu(
Key key = null,
EdgeInsets padding = null,
_DropdownRoute<T> route = null
) : base(key: key) {
this.route = route;
this.padding = padding;
}
public readonly _DropdownRoute<T> route;
public readonly EdgeInsets padding;
public override State createState() {
return new _DropdownMenuState<T>();
}
}
class _DropdownMenuState<T> : State<_DropdownMenu<T>> where T : class {
CurvedAnimation _fadeOpacity;
CurvedAnimation _resize;
public _DropdownMenuState() {
}
public override void initState() {
base.initState();
this._fadeOpacity = new CurvedAnimation(
parent: this.widget.route.animation,
curve: new Interval(0.0f, 0.25f),
reverseCurve: new Interval(0.75f, 1.0f)
);
this._resize = new CurvedAnimation(
parent: this.widget.route.animation,
curve: new Interval(0.25f, 0.5f),
reverseCurve: new Threshold(0.0f)
);
}
public override Widget build(BuildContext context) {
D.assert(MaterialD.debugCheckHasMaterialLocalizations(context));
MaterialLocalizations localizations = MaterialLocalizations.of(context);
_DropdownRoute<T> route = this.widget.route;
float unit = 0.5f / (route.items.Count + 1.5f);
List<Widget> children = new List<Widget>();
for (int itemIndex = 0; itemIndex < route.items.Count; ++itemIndex) {
CurvedAnimation opacity;
if (itemIndex == route.selectedIndex) {
opacity = new CurvedAnimation(parent: route.animation, curve: new Threshold(0.0f));
}
else {
float start = (0.5f + (itemIndex + 1) * unit).clamp(0.0f, 1.0f);
float end = (start + 1.5f * unit).clamp(0.0f, 1.0f);
opacity = new CurvedAnimation(parent: route.animation, curve: new Interval(start, end));
}
var index = itemIndex;
children.Add(new FadeTransition(
opacity: opacity,
child: new InkWell(
child: new Container(
padding: this.widget.padding,
child: route.items[itemIndex]
),
onTap: () => Navigator.pop(
context,
new _DropdownRouteResult<T>(route.items[index].value)
)
)
));
}
return new FadeTransition(
opacity: this._fadeOpacity,
child: new CustomPaint(
painter: new _DropdownMenuPainter(
color: Theme.of(context).canvasColor,
elevation: route.elevation,
selectedIndex: route.selectedIndex,
resize: this._resize
),
child: new Material(
type: MaterialType.transparency,
textStyle: route.style,
child: new ScrollConfiguration(
behavior: new _DropdownScrollBehavior(),
child: new Scrollbar(
child: new ListView(
controller: this.widget.route.scrollController,
padding: Constants.kMaterialListPadding,
itemExtent: DropdownConstants._kMenuItemHeight,
shrinkWrap: true,
children: children
)
)
)
)
)
);
}
}
class _DropdownMenuRouteLayout<T> : SingleChildLayoutDelegate {
public _DropdownMenuRouteLayout(
Rect buttonRect,
float menuTop,
float menuHeight
) {
this.buttonRect = buttonRect;
this.menuTop = menuTop;
this.menuHeight = menuHeight;
}
public readonly Rect buttonRect;
public readonly float menuTop;
public readonly float menuHeight;
public override BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
float maxHeight = Mathf.Max(0.0f, constraints.maxHeight - 2 * DropdownConstants._kMenuItemHeight);
float width = Mathf.Min(constraints.maxWidth, this.buttonRect.width);
return new BoxConstraints(
minWidth: width,
maxWidth: width,
minHeight: 0.0f,
maxHeight: maxHeight
);
}
public override Offset getPositionForChild(Size size, Size childSize) {
D.assert(() => {
Rect container = Offset.zero & size;
if (container.intersect(this.buttonRect) == this.buttonRect) {
D.assert(this.menuTop >= 0.0f);
D.assert(this.menuTop + this.menuHeight <= size.height);
}
return true;
});
float left = this.buttonRect.right.clamp(0.0f, size.width) - childSize.width;
return new Offset(left, this.menuTop);
}
public override bool shouldRelayout(SingleChildLayoutDelegate _oldDelegate) {
_DropdownMenuRouteLayout<T> oldDelegate = _oldDelegate as _DropdownMenuRouteLayout<T>;
return this.buttonRect != oldDelegate.buttonRect
|| this.menuTop != oldDelegate.menuTop
|| this.menuHeight != oldDelegate.menuHeight;
}
}
class _DropdownRouteResult<T> where T: class {
public _DropdownRouteResult(T result) {
this.result = result;
}
public readonly T result;
public static bool operator ==(_DropdownRouteResult<T> left, _DropdownRouteResult<T> right) {
return left.result == right.result;
}
public static bool operator !=(_DropdownRouteResult<T> left, _DropdownRouteResult<T> right) {
return left.result != right.result;
}
public override int GetHashCode() {
return this.result.GetHashCode();
}
}
class _DropdownRoute<T> : PopupRoute where T : class {
public _DropdownRoute(
List<DropdownMenuItem<T>> items = null,
EdgeInsets padding = null,
Rect buttonRect = null,
int? selectedIndex = null,
int elevation = 8,
ThemeData theme = null,
TextStyle style = null,
string barrierLabel = null
) {
D.assert(style != null);
this.items = items;
this.padding = padding;
this.buttonRect = buttonRect;
this.selectedIndex = selectedIndex;
this.elevation = elevation;
this.theme = theme;
this.style = style;
this.barrierLabel = barrierLabel;
}
public readonly List<DropdownMenuItem<T>> items;
public readonly EdgeInsets padding;
public readonly Rect buttonRect;
public readonly int? selectedIndex;
public readonly int elevation;
public readonly ThemeData theme;
public readonly TextStyle style;
public ScrollController scrollController;
public override TimeSpan transitionDuration {
get { return DropdownConstants._kDropdownMenuDuration; }
}
public override bool barrierDismissible {
get { return true; }
}
public override Color barrierColor {
get { return null; }
}
public string barrierLabel;
public override Widget buildPage(BuildContext context, Animation<float> animation,
Animation<float> secondaryAnimation) {
D.assert(WidgetsD.debugCheckHasDirectionality(context));
float screenHeight = MediaQuery.of(context).size.height;
float maxMenuHeight = screenHeight - 2.0f * DropdownConstants._kMenuItemHeight;
float buttonTop = this.buttonRect.top;
float buttonBottom = this.buttonRect.bottom;
float topLimit = Mathf.Min(DropdownConstants._kMenuItemHeight, buttonTop);
float bottomLimit = Mathf.Max(screenHeight - DropdownConstants._kMenuItemHeight, buttonBottom);
float? selectedItemOffset = this.selectedIndex * DropdownConstants._kMenuItemHeight +
Constants.kMaterialListPadding.top;
float? menuTop = (buttonTop - selectedItemOffset) -
(DropdownConstants._kMenuItemHeight - this.buttonRect.height) / 2.0f;
float preferredMenuHeight = (this.items.Count * DropdownConstants._kMenuItemHeight) +
Constants.kMaterialListPadding.vertical;
float menuHeight = Mathf.Min(maxMenuHeight, preferredMenuHeight);
float? menuBottom = menuTop + menuHeight;
if (menuTop < topLimit) {
menuTop = Mathf.Min(buttonTop, topLimit);
}
if (menuBottom > bottomLimit) {
menuBottom = Mathf.Max(buttonBottom, bottomLimit);
menuTop = menuBottom - menuHeight;
}
if (this.scrollController == null) {
float scrollOffset = preferredMenuHeight > maxMenuHeight
? Mathf.Max(0.0f, selectedItemOffset ?? 0.0f - (buttonTop - (menuTop ?? 0.0f)))
: 0.0f;
this.scrollController = new ScrollController(initialScrollOffset: scrollOffset);
}
Widget menu = new _DropdownMenu<T>(
route: this,
padding: this.padding
);
if (this.theme != null) {
menu = new Theme(data: this.theme, child: menu);
}
return MediaQuery.removePadding(
context: context,
removeTop: true,
removeBottom: true,
removeLeft: true,
removeRight: true,
child: new Builder(
builder: (BuildContext _context) => {
return new CustomSingleChildLayout(
layoutDelegate: new _DropdownMenuRouteLayout<T>(
buttonRect: this.buttonRect,
menuTop: menuTop ?? 0.0f,
menuHeight: menuHeight
),
child: menu
);
}
)
);
}
public void _dismiss() {
this.navigator?.removeRoute(this);
}
}
public class DropdownMenuItem<T> : StatelessWidget where T : class {
public DropdownMenuItem(
Key key = null,
T value = null,
Widget child = null
) : base(key: key) {
D.assert(child != null);
this.value = value;
this.child = child;
}
public readonly Widget child;
public readonly T value;
public override Widget build(BuildContext context) {
return new Container(
height: DropdownConstants._kMenuItemHeight,
alignment: Alignment.centerLeft,
child: this.child
);
}
}
public class DropdownButtonHideUnderline : InheritedWidget {
public DropdownButtonHideUnderline(
Key key = null,
Widget child = null
) : base(key: key, child: child) {
D.assert(child != null);
}
public static bool at(BuildContext context) {
return context.inheritFromWidgetOfExactType(typeof(DropdownButtonHideUnderline)) != null;
}
public override bool updateShouldNotify(InheritedWidget oldWidget) {
return false;
}
}
public class DropdownButton<T> : StatefulWidget where T : class {
public DropdownButton(
Key key = null,
List<DropdownMenuItem<T>> items = null,
T value = null,
Widget hint = null,
Widget disabledHint = null,
ValueChanged<T> onChanged = null,
int elevation = 8,
TextStyle style = null,
float iconSize = 24.0f,
bool isDense = false,
bool isExpanded = false
) :
base(key: key) {
D.assert(items == null || value == null ||
items.Where<DropdownMenuItem<T>>((DropdownMenuItem<T> item) => item.value.Equals(value)).ToList()
.Count == 1);
this.items = items;
this.value = value;
this.hint = hint;
this.disabledHint = disabledHint;
this.onChanged = onChanged;
this.elevation = elevation;
this.style = style;
this.iconSize = iconSize;
this.isDense = isDense;
this.isExpanded = isExpanded;
}
public readonly List<DropdownMenuItem<T>> items;
public readonly T value;
public readonly Widget hint;
public readonly Widget disabledHint;
public readonly ValueChanged<T> onChanged;
public readonly int elevation;
public readonly TextStyle style;
public readonly float iconSize;
public readonly bool isDense;
public readonly bool isExpanded;
public override State createState() {
return new _DropdownButtonState<T>();
}
}
class _DropdownButtonState<T> : State<DropdownButton<T>>, WidgetsBindingObserver where T : class {
int? _selectedIndex;
_DropdownRoute<T> _dropdownRoute;
public void didChangeTextScaleFactor() {
}
public void didChangeLocales(List<Locale> locale) {
}
public IPromise<bool> didPopRoute() {
return Promise<bool>.Resolved(false);
}
public IPromise<bool> didPushRoute(string route) {
return Promise<bool>.Resolved(false);
}
public override void initState() {
base.initState();
this._updateSelectedIndex();
WidgetsBinding.instance.addObserver(this);
}
public override void dispose() {
WidgetsBinding.instance.removeObserver(this);
this._removeDropdownRoute();
base.dispose();
}
public void didChangeMetrics() {
this._removeDropdownRoute();
}
void _removeDropdownRoute() {
this._dropdownRoute?._dismiss();
this._dropdownRoute = null;
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
this._updateSelectedIndex();
}
void _updateSelectedIndex() {
if (!this._enabled) {
return;
}
D.assert(this.widget.value == null ||
this.widget.items.Where((DropdownMenuItem<T> item) => item.value.Equals(this.widget.value))
.ToList().Count == 1);
this._selectedIndex = null;
for (int itemIndex = 0; itemIndex < this.widget.items.Count; itemIndex++) {
if (this.widget.items[itemIndex].value.Equals(this.widget.value)) {
this._selectedIndex = itemIndex;
return;
}
}
}
TextStyle _textStyle {
get { return this.widget.style ?? Theme.of(this.context).textTheme.subhead; }
}
void _handleTap() {
RenderBox itemBox = (RenderBox) this.context.findRenderObject();
Rect itemRect = itemBox.localToGlobal(Offset.zero) & itemBox.size;
EdgeInsets menuMargin = ButtonTheme.of(this.context).alignedDropdown
? DropdownConstants._kAlignedMenuMargin
: DropdownConstants._kUnalignedMenuMargin;
D.assert(this._dropdownRoute == null);
this._dropdownRoute = new _DropdownRoute<T>(
items: this.widget.items,
buttonRect: menuMargin.inflateRect(itemRect),
padding: DropdownConstants._kMenuItemPadding,
selectedIndex: this._selectedIndex ?? 0,
elevation: this.widget.elevation,
theme: Theme.of(this.context, shadowThemeOnly: true),
style: this._textStyle,
barrierLabel: MaterialLocalizations.of(this.context).modalBarrierDismissLabel
);
Navigator.push(this.context, this._dropdownRoute).Then(newValue => {
_DropdownRouteResult<T> value = newValue as _DropdownRouteResult<T>;
this._dropdownRoute = null;
if (!this.mounted || newValue == null) {
return;
}
if (this.widget.onChanged != null) {
this.widget.onChanged(value.result);
}
});
}
float? _denseButtonHeight {
get {
return Mathf.Max(this._textStyle.fontSize ?? 0.0f,
Mathf.Max(this.widget.iconSize, DropdownConstants._kDenseButtonHeight));
}
}
Color _downArrowColor {
get {
if (this._enabled) {
if (Theme.of(this.context).brightness == Brightness.light) {
return Colors.grey.shade700;
}
else {
return Colors.white70;
}
}
else {
if (Theme.of(this.context).brightness == Brightness.light) {
return Colors.grey.shade400;
}
else {
return Colors.white10;
}
}
}
}
bool _enabled {
get { return this.widget.items != null && this.widget.items.isNotEmpty() && this.widget.onChanged != null; }
}
public override Widget build(BuildContext context) {
D.assert(MaterialD.debugCheckHasMaterial(context));
D.assert(MaterialD.debugCheckHasMaterialLocalizations(context));
List<Widget> items = this._enabled ? new List<Widget>(this.widget.items) : new List<Widget>();
int hintIndex = 0;
if (this.widget.hint != null || (!this._enabled && this.widget.disabledHint != null)) {
Widget emplacedHint =
this._enabled
? this.widget.hint
: new DropdownMenuItem<Widget>(child: this.widget.disabledHint ?? this.widget.hint);
hintIndex = items.Count;
items.Add(new DefaultTextStyle(
style: this._textStyle.copyWith(color: Theme.of(context).hintColor),
child: new IgnorePointer(
child: emplacedHint
)
));
}
EdgeInsets padding = ButtonTheme.of(context).alignedDropdown
? DropdownConstants._kAlignedButtonPadding
: DropdownConstants._kUnalignedButtonPadding;
IndexedStack innerItemsWidget = new IndexedStack(
index: this._enabled ? (this._selectedIndex ?? hintIndex) : hintIndex,
alignment: Alignment.centerLeft,
children: items
);
Widget result = new DefaultTextStyle(
style: this._textStyle,
child: new Container(
padding: padding,
height: this.widget.isDense ? this._denseButtonHeight : null,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {
this.widget.isExpanded ? new Expanded(child: innerItemsWidget) : (Widget) innerItemsWidget,
new Icon(Icons.arrow_drop_down,
size: this.widget.iconSize,
color: this._downArrowColor
)
}
)
)
);
if (!DropdownButtonHideUnderline.at(context)) {
float bottom = this.widget.isDense ? 0.0f : 8.0f;
result = new Stack(
children: new List<Widget> {
result,
new Positioned(
left: 0.0f,
right: 0.0f,
bottom: bottom,
child: new Container(
height: 1.0f,
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(color: new Color(0xFFBDBDBD), width: 0.0f))
)
)
)
}
);
}
return new GestureDetector(
onTap: this._enabled ? (GestureTapCallback) this._handleTap : null,
behavior: HitTestBehavior.opaque,
child: result
);
}
}
public class DropdownButtonFormField<T> : FormField<T> where T : class {
public DropdownButtonFormField(
Key key = null,
T value = null,
List<DropdownMenuItem<T>> items = null,
ValueChanged<T> onChanged = null,
InputDecoration decoration = null,
FormFieldSetter<T> onSaved = null,
FormFieldValidator<T> validator = null,
Widget hint = null
) : base(
key: key,
onSaved: onSaved,
initialValue: value,
validator: validator,
builder: (FormFieldState<T> field) => {
InputDecoration effectiveDecoration = (decoration ?? new InputDecoration())
.applyDefaults(Theme.of(field.context).inputDecorationTheme);
return new InputDecorator(
decoration: effectiveDecoration.copyWith(errorText: field.errorText),
isEmpty: value == null,
child: new DropdownButtonHideUnderline(
child: new DropdownButton<T>(
isDense: true,
value: value,
items: items,
hint: hint,
onChanged: field.didChange
)
)
);
}
) {
this.onChanged = onChanged;
}
public readonly ValueChanged<T> onChanged;
public override State createState() {
return new _DropdownButtonFormFieldState<T>();
}
}
class _DropdownButtonFormFieldState<T> : FormFieldState<T> where T : class {
public DropdownButtonFormField<T> widget {
get { return base.widget as DropdownButtonFormField<T>; }
}
public override void didChange(T value) {
base.didChange(value);
if (this.widget.onChanged != null) {
this.widget.onChanged(value);
}
}
}
}

3
Runtime/material/dropdown.cs.meta


fileFormatVersion: 2
guid: 54d382ec712d4e87b802716ca97c1f3d
timeCreated: 1552537966

368
Runtime/material/input_border.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.material {
public abstract class InputBorder : ShapeBorder {
public InputBorder(
BorderSide borderSide = null
) {
this.borderSide = borderSide ?? BorderSide.none;
}
public static readonly InputBorder none = new _NoInputBorder();
public readonly BorderSide borderSide;
public abstract InputBorder copyWith(BorderSide borderSide = null);
public virtual bool isOutline { get; }
public abstract void paint(Canvas canvas, Rect rect,
float gapStart,
float gapExtent = 0.0f,
float gapPercentage = 0.0f
);
public override void paint(Canvas canvas, Rect rect) {
this.paint(canvas, rect, 0.0f);
}
}
class _NoInputBorder : InputBorder {
public _NoInputBorder() : base(borderSide: BorderSide.none) {
}
public override InputBorder copyWith(BorderSide borderSide) {
return new _NoInputBorder();
}
public override bool isOutline {
get { return false; }
}
public override EdgeInsets dimensions {
get { return EdgeInsets.zero; }
}
public override ShapeBorder scale(float t) {
return new _NoInputBorder();
}
public override Path getInnerPath(Rect rect) {
Path path = new Path();
path.addRect(rect);
return path;
}
public override Path getOuterPath(Rect rect) {
Path path = new Path();
path.addRect(rect);
return path;
}
public override void paint(Canvas canvas, Rect rect,
float gapStart,
float gapExtent = 0.0f,
float gapPercentage = 0.0f
) {
}
}
public class UnderlineInputBorder : InputBorder {
public UnderlineInputBorder(
BorderSide borderSide = null,
BorderRadius borderRadius = null
) : base(borderSide: borderSide ?? new BorderSide()) {
this.borderRadius = borderRadius ?? BorderRadius.only(
topLeft: Radius.circular(4.0f),
topRight: Radius.circular(4.0f)
);
}
public readonly BorderRadius borderRadius;
public override bool isOutline {
get { return false; }
}
public UnderlineInputBorder copyWith(BorderSide borderSide = null, BorderRadius borderRadius = null) {
return new UnderlineInputBorder(
borderSide: borderSide ?? this.borderSide,
borderRadius: borderRadius ?? this.borderRadius
);
}
public override InputBorder copyWith(BorderSide borderSide = null) {
return new UnderlineInputBorder(
borderSide: borderSide ?? this.borderSide
);
}
public override EdgeInsets dimensions {
get { return EdgeInsets.only(bottom: this.borderSide.width); }
}
public override ShapeBorder scale(float t) {
return new UnderlineInputBorder(borderSide: this.borderSide.scale(t));
}
public override Path getInnerPath(Rect rect) {
Path path = new Path();
path.addRect(Rect.fromLTWH(rect.left, rect.top, rect.width,
Mathf.Max(0.0f, rect.height - this.borderSide.width)));
return path;
}
public override Path getOuterPath(Rect rect) {
Path path = new Path();
path.addRRect(this.borderRadius.toRRect(rect));
return path;
}
public override ShapeBorder lerpFrom(ShapeBorder a, float t) {
if (a is UnderlineInputBorder) {
return new UnderlineInputBorder(
borderSide: BorderSide.lerp((a as UnderlineInputBorder).borderSide, this.borderSide, t),
borderRadius: BorderRadius.lerp((a as UnderlineInputBorder).borderRadius, this.borderRadius, t)
);
}
return base.lerpFrom(a, t);
}
public override ShapeBorder lerpTo(ShapeBorder b, float t) {
if (b is UnderlineInputBorder) {
return new UnderlineInputBorder(
borderSide: BorderSide.lerp(this.borderSide, (b as UnderlineInputBorder).borderSide, t),
borderRadius: BorderRadius.lerp(this.borderRadius, (b as UnderlineInputBorder).borderRadius, t)
);
}
return base.lerpTo(b, t);
}
public override void paint(Canvas canvas, Rect rect,
float gapStart,
float gapExtent = 0.0f,
float gapPercentage = 0.0f
) {
if (this.borderRadius.bottomLeft != Radius.zero || this.borderRadius.bottomRight != Radius.zero) {
canvas.clipPath(this.getOuterPath(rect));
}
canvas.drawLine(rect.bottomLeft, rect.bottomRight, this.borderSide.toPaint());
}
public static bool operator ==(UnderlineInputBorder left, UnderlineInputBorder other) {
return left.borderSide == other.borderSide;
}
public static bool operator !=(UnderlineInputBorder left, UnderlineInputBorder other) {
return left.borderSide != other.borderSide;
}
public override int GetHashCode() {
return this.borderSide.GetHashCode();
}
}
public class OutlineInputBorder : InputBorder {
public OutlineInputBorder(
BorderSide borderSide = null,
BorderRadius borderRadius = null,
float gapPadding = 4.0f
) : base(borderSide: borderSide ?? new BorderSide()) {
D.assert(gapPadding >= 0.0f);
this.gapPadding = gapPadding;
this.borderRadius = borderRadius ?? BorderRadius.all(Radius.circular(4.0f));
}
static bool _cornersAreCircular(BorderRadius borderRadius) {
return borderRadius.topLeft.x == borderRadius.topLeft.y
&& borderRadius.bottomLeft.x == borderRadius.bottomLeft.y
&& borderRadius.topRight.x == borderRadius.topRight.y
&& borderRadius.bottomRight.x == borderRadius.bottomRight.y;
}
public readonly float gapPadding;
public readonly BorderRadius borderRadius;
public override bool isOutline {
get { return true; }
}
public OutlineInputBorder copyWith(
BorderSide borderSide,
BorderRadius borderRadius,
float? gapPadding
) {
return new OutlineInputBorder(
borderSide: borderSide ?? this.borderSide,
borderRadius: borderRadius ?? this.borderRadius,
gapPadding: gapPadding ?? this.gapPadding
);
}
public override InputBorder copyWith(BorderSide borderSide) {
return new OutlineInputBorder(
borderSide: borderSide ?? this.borderSide,
borderRadius: this.borderRadius,
gapPadding: this.gapPadding
);
}
public override EdgeInsets dimensions {
get { return EdgeInsets.all(this.borderSide.width); }
}
public override ShapeBorder scale(float t) {
return new OutlineInputBorder(
borderSide: this.borderSide.scale(t),
borderRadius: this.borderRadius * t,
gapPadding: this.gapPadding * t
);
}
public override ShapeBorder lerpFrom(ShapeBorder a, float t) {
if (a is OutlineInputBorder) {
OutlineInputBorder outline = a as OutlineInputBorder;
return new OutlineInputBorder(
borderRadius: BorderRadius.lerp(outline.borderRadius, this.borderRadius, t),
borderSide: BorderSide.lerp(outline.borderSide, this.borderSide, t),
gapPadding: outline.gapPadding
);
}
return base.lerpFrom(a, t);
}
public override ShapeBorder lerpTo(ShapeBorder b, float t) {
if (b is OutlineInputBorder) {
OutlineInputBorder outline = b as OutlineInputBorder;
return new OutlineInputBorder(
borderRadius: BorderRadius.lerp(this.borderRadius, outline.borderRadius, t),
borderSide: BorderSide.lerp(this.borderSide, outline.borderSide, t),
gapPadding: outline.gapPadding
);
}
return base.lerpTo(b, t);
}
public override Path getInnerPath(Rect rect) {
Path path = new Path();
path.addRRect(this.borderRadius.toRRect(rect).deflate(this.borderSide.width));
return path;
}
public override Path getOuterPath(Rect rect) {
Path path = new Path();
path.addRRect(this.borderRadius.toRRect(rect));
return path;
}
Path _gapBorderPath(Canvas canvas, RRect center, float start, float extent) {
Rect tlCorner = Rect.fromLTWH(
center.left,
center.top,
center.tlRadiusX * 2.0f,
center.tlRadiusY * 2.0f
);
Rect trCorner = Rect.fromLTWH(
center.right - center.trRadiusX * 2.0f,
center.top,
center.trRadiusX * 2.0f,
center.trRadiusY * 2.0f
);
Rect brCorner = Rect.fromLTWH(
center.right - center.brRadiusX * 2.0f,
center.bottom - center.brRadiusY * 2.0f,
center.brRadiusX * 2.0f,
center.brRadiusY * 2.0f
);
Rect blCorner = Rect.fromLTWH(
center.left,
center.bottom - center.brRadiusY * 2.0f,
center.blRadiusX * 2.0f,
center.blRadiusY * 2.0f
);
const float cornerArcSweep = Mathf.PI / 2.0f;
float tlCornerArcSweep = start < center.tlRadiusX
? Mathf.Asin(start / center.tlRadiusX)
: Mathf.PI / 2.0f;
Path path = new Path();
path.addArc(tlCorner, Mathf.PI, tlCornerArcSweep);
path.moveTo(center.left + center.tlRadiusX, center.top);
if (start > center.tlRadiusX) {
path.lineTo(center.left + start, center.top);
}
const float trCornerArcStart = (3 * Mathf.PI) / 2.0f;
const float trCornerArcSweep = cornerArcSweep;
if (start + extent < center.width - center.trRadiusX) {
path.relativeMoveTo(extent, 0.0f);
path.lineTo(center.right - center.trRadiusX, center.top);
path.addArc(trCorner, trCornerArcStart, trCornerArcSweep);
}
else if (start + extent < center.width) {
float dx = center.width - (start + extent);
float sweep = Mathf.Acos(dx / center.trRadiusX);
path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep);
}
path.moveTo(center.right, center.top + center.trRadiusY);
path.lineTo(center.right, center.bottom - center.brRadiusY);
path.addArc(brCorner, 0.0f, cornerArcSweep);
path.lineTo(center.left + center.blRadiusX, center.bottom);
path.addArc(blCorner, Mathf.PI / 2.0f, cornerArcSweep);
path.lineTo(center.left, center.top + center.trRadiusY);
return path;
}
public override void paint(Canvas canvas, Rect rect,
float gapStart,
float gapExtent = 0.0f,
float gapPercentage = 0.0f
) {
D.assert(gapPercentage >= 0.0f && gapPercentage <= 1.0f);
D.assert(_cornersAreCircular(this.borderRadius));
Paint paint = this.borderSide.toPaint();
RRect outer = this.borderRadius.toRRect(rect);
RRect center = outer.deflate(this.borderSide.width / 2.0f);
if (gapExtent <= 0.0f || gapPercentage == 0.0f) {
canvas.drawRRect(center, paint);
}
else {
float extent = MathUtils.lerpFloat(0.0f, gapExtent + this.gapPadding * 2.0f, gapPercentage);
Path path = this._gapBorderPath(canvas, center, gapStart - this.gapPadding, extent);
canvas.drawPath(path, paint);
}
}
public static bool operator ==(OutlineInputBorder left, OutlineInputBorder other) {
return other.borderSide == left.borderSide
&& other.borderRadius == left.borderRadius
&& other.gapPadding == left.gapPadding;
}
public static bool operator !=(OutlineInputBorder left, OutlineInputBorder other) {
return !(left == other);
}
public override int GetHashCode() {
var hashCode = this.borderSide.GetHashCode();
hashCode = (hashCode * 397) ^ this.borderRadius.GetHashCode();
hashCode = (hashCode * 397) ^ this.gapPadding.GetHashCode();
return hashCode;
}
}
}

3
Runtime/material/input_border.cs.meta


fileFormatVersion: 2
guid: 6431f8efd0b444ea9982ff6d0a0e74f4
timeCreated: 1552619063

1001
Runtime/material/input_decorator.cs
文件差异内容过多而无法显示
查看文件

3
Runtime/material/input_decorator.cs.meta


fileFormatVersion: 2
guid: 2106361ab28b4560a12fdbae0f1b1c8f
timeCreated: 1552548801

460
Runtime/material/outline_button.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.material {
class OutlineButtonConstants {
public static readonly TimeSpan _kPressDuration = new TimeSpan(0, 0, 0, 0, 150);
public static readonly TimeSpan _kElevationDuration = new TimeSpan(0, 0, 0, 0, 75);
}
public class OutlineButton : MaterialButton {
public OutlineButton(
Key key = null,
VoidCallback onPressed = null,
ButtonTextTheme? textTheme = null,
Color textColor = null,
Color disabledTextColor = null,
Color color = null,
Color highlightColor = null,
Color splashColor = null,
float? highlightElevation = null,
BorderSide borderSide = null,
Color disabledBorderColor = null,
Color highlightedBorderColor = null,
EdgeInsets padding = null,
ShapeBorder shape = null,
Clip clipBehavior = Clip.none,
Widget child = null
) :
base(
key: key,
onPressed: onPressed,
textTheme: textTheme,
textColor: textColor,
disabledTextColor: disabledTextColor,
color: color,
highlightColor: highlightColor,
splashColor: splashColor,
highlightElevation: highlightElevation,
padding: padding,
shape: shape,
clipBehavior: clipBehavior,
child: child
) {
D.assert(highlightElevation == null || highlightElevation >= 0.0f);
D.assert(onPressed != null);
this.highlightedBorderColor = highlightedBorderColor;
this.disabledBorderColor = disabledBorderColor;
this.borderSide = borderSide;
}
public static OutlineButton icon(
Key key = null,
VoidCallback onPressed = null,
ButtonTextTheme? textTheme = null,
Color textColor = null,
Color disabledTextColor = null,
Color color = null,
Color highlightColor = null,
Color splashColor = null,
float? highlightElevation = null,
Color highlightedBorderColor = null,
Color disabledBorderColor = null,
BorderSide borderSide = null,
EdgeInsets padding = null,
ShapeBorder shape = null,
Clip clipBehavior = Clip.none,
Widget icon = null,
Widget label = null
) {
return new _OutlineButtonWithIcon(
key,
onPressed,
textTheme,
textColor,
disabledTextColor,
color,
highlightColor,
splashColor,
highlightElevation,
highlightedBorderColor,
disabledBorderColor,
borderSide,
padding,
shape,
clipBehavior,
icon,
label
);
}
public readonly Color highlightedBorderColor;
public readonly Color disabledBorderColor;
public readonly BorderSide borderSide;
public override Widget build(BuildContext context) {
ButtonThemeData buttonTheme = ButtonTheme.of(context);
return new _OutlineButton(
onPressed: this.onPressed,
brightness: buttonTheme.getBrightness(this),
textTheme: this.textTheme,
textColor: buttonTheme.getTextColor(this),
disabledTextColor: buttonTheme.getDisabledTextColor(this),
color: this.color,
highlightColor: buttonTheme.getHighlightColor(this),
splashColor: buttonTheme.getSplashColor(this),
highlightElevation: buttonTheme.getHighlightElevation(this),
borderSide: this.borderSide,
disabledBorderColor: this.disabledBorderColor,
highlightedBorderColor: this.highlightedBorderColor ?? buttonTheme.colorScheme.primary,
padding: buttonTheme.getPadding(this),
shape: buttonTheme.getShape(this),
clipBehavior: this.clipBehavior,
child: this.child
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new ObjectFlagProperty<VoidCallback>("onPressed", this.onPressed, ifNull: "disabled"));
properties.add(new DiagnosticsProperty<ButtonTextTheme?>("textTheme", this.textTheme, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("textColor", this.textColor, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("disabledTextColor", this.disabledTextColor,
defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("color", this.color, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("highlightColor", this.highlightColor, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("splashColor", this.splashColor, defaultValue: null));
properties.add(new DiagnosticsProperty<float?>("highlightElevation", this.highlightElevation,
defaultValue: null));
properties.add(new DiagnosticsProperty<BorderSide>("borderSide", this.borderSide, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("disabledBorderColor", this.disabledBorderColor,
defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("highlightedBorderColor", this.highlightedBorderColor,
defaultValue: null));
properties.add(new DiagnosticsProperty<EdgeInsets>("padding", this.padding, defaultValue: null));
properties.add(new DiagnosticsProperty<ShapeBorder>("shape", this.shape, defaultValue: null));
}
}
class _OutlineButtonWithIcon : OutlineButton, MaterialButtonWithIconMixin {
public _OutlineButtonWithIcon(
Key key = null,
VoidCallback onPressed = null,
ButtonTextTheme? textTheme = null,
Color textColor = null,
Color disabledTextColor = null,
Color color = null,
Color highlightColor = null,
Color splashColor = null,
float? highlightElevation = null,
Color highlightedBorderColor = null,
Color disabledBorderColor = null,
BorderSide borderSide = null,
EdgeInsets padding = null,
ShapeBorder shape = null,
Clip clipBehavior = Clip.none,
Widget icon = null,
Widget label = null
) :
base(
key: key,
onPressed: onPressed,
textTheme: textTheme,
textColor: textColor,
disabledTextColor: disabledTextColor,
color: color,
highlightColor: highlightColor,
splashColor: splashColor,
highlightElevation: highlightElevation,
disabledBorderColor: disabledBorderColor,
highlightedBorderColor: highlightedBorderColor,
borderSide: borderSide,
padding: padding,
shape: shape,
clipBehavior: clipBehavior,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {
icon,
new SizedBox(width: 8.0f),
label
}
)
) {
D.assert(onPressed != null);
D.assert(highlightElevation == null || highlightElevation >= 0.0f);
D.assert(icon != null);
D.assert(label != null);
}
}
class _OutlineButton : StatefulWidget {
public _OutlineButton(
Key key = null,
VoidCallback onPressed = null,
Brightness? brightness = null,
ButtonTextTheme? textTheme = null,
Color textColor = null,
Color disabledTextColor = null,
Color color = null,
Color highlightColor = null,
Color splashColor = null,
float? highlightElevation = null,
BorderSide borderSide = null,
Color disabledBorderColor = null,
Color highlightedBorderColor = null,
EdgeInsets padding = null,
ShapeBorder shape = null,
Clip? clipBehavior = Clip.none,
Widget child = null
) : base(key: key) {
D.assert(highlightElevation != null && highlightElevation >= 0.0f);
D.assert(highlightedBorderColor != null);
D.assert(this.onPressed != null);
this.onPressed = onPressed;
this.brightness = brightness;
this.textTheme = textTheme;
this.textColor = textColor;
this.disabledTextColor = disabledTextColor;
this.color = color;
this.highlightColor = highlightColor;
this.splashColor = splashColor;
this.highlightElevation = highlightElevation;
this.borderSide = borderSide;
this.disabledBorderColor = disabledBorderColor;
this.highlightedBorderColor = highlightedBorderColor;
this.padding = padding;
this.shape = shape;
this.clipBehavior = clipBehavior;
this.child = child;
}
public readonly VoidCallback onPressed;
public readonly Brightness? brightness;
public readonly ButtonTextTheme? textTheme;
public readonly Color textColor;
public readonly Color disabledTextColor;
public readonly Color color;
public readonly Color highlightColor;
public readonly Color splashColor;
public readonly float? highlightElevation;
public readonly BorderSide borderSide;
public readonly Color disabledBorderColor;
public readonly Color highlightedBorderColor;
public readonly EdgeInsets padding;
public readonly ShapeBorder shape;
public readonly Clip? clipBehavior;
public readonly Widget child;
public bool enabled {
get { return this.onPressed != null; }
}
public override State createState() {
return new _OutlineButtonState();
}
}
class _OutlineButtonState : SingleTickerProviderStateMixin<_OutlineButton> {
AnimationController _controller;
Animation<float> _fillAnimation;
Animation<float> _elevationAnimation;
bool _pressed = false;
public override void initState() {
base.initState();
this._controller = new AnimationController(
duration: OutlineButtonConstants._kPressDuration,
vsync: this
);
this._fillAnimation = new CurvedAnimation(
parent: this._controller,
curve: new Interval(0.0f, 0.5f,
curve: Curves.fastOutSlowIn
)
);
this._elevationAnimation = new CurvedAnimation(
parent: this._controller,
curve: new Interval(0.5f, 0.5f),
reverseCurve: new Interval(1.0f, 1.0f)
);
}
public override void dispose() {
this._controller.dispose();
base.dispose();
}
Color _getFillColor() {
bool themeIsDark = this.widget.brightness == Brightness.dark;
Color color = this.widget.color ?? (themeIsDark
? new Color(0x00000000)
: new Color(0x00FFFFFF));
ColorTween colorTween = new ColorTween(
begin: color.withAlpha(0x00),
end: color.withAlpha(0xFF)
);
return colorTween.evaluate(this._fillAnimation);
}
BorderSide _getOutline() {
bool isDark = this.widget.brightness == Brightness.dark;
if (this.widget.borderSide?.style == BorderStyle.none) {
return this.widget.borderSide;
}
Color color = this.widget.enabled
? (this._pressed
? this.widget.highlightedBorderColor
: (this.widget.borderSide?.color ??
(isDark ? Colors.grey[600] : Colors.grey[200])))
: (this.widget.disabledBorderColor ??
(isDark ? Colors.grey[800] : Colors.grey[100]));
return new BorderSide(
color: color,
width: this.widget.borderSide?.width ?? 2.0f
);
}
float _getHighlightElevation() {
return new FloatTween(
begin: 0.0f,
end: this.widget.highlightElevation ?? 2.0f
).evaluate(this._elevationAnimation);
}
public override Widget build(BuildContext context) {
return new AnimatedBuilder(
animation: this._controller,
builder: (BuildContext _context, Widget child) => {
return new RaisedButton(
textColor: this.widget.textColor,
disabledTextColor: this.widget.disabledTextColor,
color: this._getFillColor(),
splashColor: this.widget.splashColor,
highlightColor: this.widget.highlightColor,
disabledColor: Colors.transparent,
onPressed: this.widget.onPressed,
elevation: 0.0f,
disabledElevation: 0.0f,
highlightElevation: this._getHighlightElevation(),
onHighlightChanged: (bool value) => {
this.setState(() => {
this._pressed = value;
if (value) {
this._controller.forward();
}
else {
this._controller.reverse();
}
});
},
padding:
this.widget.padding,
shape: new _OutlineBorder(
shape: this.widget.shape,
side: this._getOutline()
),
clipBehavior:
this.widget.clipBehavior,
animationDuration: OutlineButtonConstants._kElevationDuration,
child:
this.widget.child
);
}
);
}
}
class _OutlineBorder : ShapeBorder {
public _OutlineBorder(
ShapeBorder shape,
BorderSide side
) {
D.assert(shape != null);
D.assert(side != null);
this.shape = shape;
this.side = side;
}
public readonly ShapeBorder shape;
public readonly BorderSide side;
public override EdgeInsets dimensions {
get { return EdgeInsets.all(this.side.width); }
}
public override ShapeBorder scale(float t) {
return new _OutlineBorder(
shape: this.shape.scale(t),
side: this.side.scale(t)
);
}
public override ShapeBorder lerpFrom(ShapeBorder a, float t) {
if (a is _OutlineBorder) {
return new _OutlineBorder(
side: BorderSide.lerp((a as _OutlineBorder).side, this.side, t),
shape: lerp((a as _OutlineBorder).shape, this.shape, t)
);
}
return base.lerpFrom(a, t);
}
public override ShapeBorder lerpTo(ShapeBorder b, float t) {
if (b is _OutlineBorder) {
return new _OutlineBorder(
side: BorderSide.lerp(this.side, (b as _OutlineBorder).side, t),
shape: lerp(this.shape, (b as _OutlineBorder).shape, t)
);
}
return base.lerpTo(b, t);
}
public override Path getInnerPath(Rect rect) {
return this.shape.getInnerPath(rect.deflate(this.side.width));
}
public override Path getOuterPath(Rect rect) {
return this.shape.getOuterPath(rect);
}
public override void paint(Canvas canvas, Rect rect) {
switch (this.side.style) {
case BorderStyle.none:
break;
case BorderStyle.solid:
canvas.drawPath(this.shape.getOuterPath(rect), this.side.toPaint());
break;
}
}
public static bool operator ==(_OutlineBorder left, _OutlineBorder other) {
return left.side == other.side && left.shape == other.shape;
}
public static bool operator !=(_OutlineBorder left, _OutlineBorder other) {
return left.side != other.side || left.shape != other.shape;
}
public override int GetHashCode() {
return (this.shape.GetHashCode() * 397) ^ this.side.GetHashCode();
}
}
}

3
Runtime/material/outline_button.cs.meta


fileFormatVersion: 2
guid: 5c535b1d86054795b33e7f0f358d957a
timeCreated: 1552641292

530
Runtime/material/progress_indicator.cs


using System;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
namespace Unity.UIWidgets.material {
class _ProgressIndicatorContants {
public const float _kLinearProgressIndicatorHeight = 6.0f;
public const float _kMinCircularProgressIndicatorSize = 36.0f;
public const int _kIndeterminateLinearDuration = 1800;
public static readonly Animatable<float> _kStrokeHeadTween = new CurveTween(
curve: new Interval(0.0f, 0.5f, curve: Curves.fastOutSlowIn)
).chain(new CurveTween(
curve: new SawTooth(5)
));
public static readonly Animatable<float> _kStrokeTailTween = new CurveTween(
curve: new Interval(0.5f, 1.0f, curve: Curves.fastOutSlowIn)
).chain(new CurveTween(
curve: new SawTooth(5)
));
public static readonly Animatable<int> _kStepTween = new StepTween(begin: 0, end: 5);
public static readonly Animatable<float> _kRotationTween = new CurveTween(curve: new SawTooth(5));
}
public abstract class ProgressIndicator : StatefulWidget {
public ProgressIndicator(
Key key = null,
float? value = null,
Color backgroundColor = null,
Animation<Color> valueColor = null
) : base(key: key) {
this.value = value;
this.backgroundColor = backgroundColor;
this.valueColor = valueColor;
}
public readonly float? value;
public readonly Color backgroundColor;
public readonly Animation<Color> valueColor;
public Color _getBackgroundColor(BuildContext context) {
return this.backgroundColor ?? Theme.of(context).backgroundColor;
}
public Color _getValueColor(BuildContext context) {
return this.valueColor?.value ?? Theme.of(context).accentColor;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new PercentProperty("value", this.value ?? 0.0f, showName: false,
ifNull: "<indeterminate>"));
}
}
class _LinearProgressIndicatorPainter : AbstractCustomPainter {
public _LinearProgressIndicatorPainter(
Color backgroundColor = null,
Color valueColor = null,
float? value = null,
float? animationValue = null
) {
this.backgroundColor = backgroundColor;
this.valueColor = valueColor;
this.value = value;
this.animationValue = animationValue;
}
public readonly Color backgroundColor;
public readonly Color valueColor;
public readonly float? value;
public readonly float? animationValue;
static readonly Curve line1Head = new Interval(
0.0f,
750.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration,
curve: new Cubic(0.2f, 0.0f, 0.8f, 1.0f)
);
static readonly Curve line1Tail = new Interval(
333.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration,
(333.0f + 750.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration,
curve: new Cubic(0.4f, 0.0f, 1.0f, 1.0f)
);
static readonly Curve line2Head = new Interval(
1000.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration,
(1000.0f + 567.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration,
curve: new Cubic(0.0f, 0.0f, 0.65f, 1.0f)
);
static readonly Curve line2Tail = new Interval(
1267.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration,
(1267.0f + 533.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration,
curve: new Cubic(0.10f, 0.0f, 0.45f, 1.0f)
);
public override void paint(Canvas canvas, Size size) {
Paint paint = new Paint();
paint.color = this.backgroundColor;
paint.style = PaintingStyle.fill;
canvas.drawRect(Offset.zero & size, paint);
paint.color = this.valueColor;
void drawBar(float x, float width) {
if (width <= 0.0f) {
return;
}
float left = x;
canvas.drawRect(new Offset(left, 0.0f) & new Size(width, size.height), paint);
}
if (this.value != null) {
drawBar(0.0f, this.value.Value.clamp(0.0f, 1.0f) * size.width);
}
else {
float x1 = size.width * line1Tail.transform(this.animationValue ?? 0.0f);
float width1 = size.width * line1Head.transform(this.animationValue ?? 0.0f) - x1;
float x2 = size.width * line2Tail.transform(this.animationValue ?? 0.0f);
float width2 = size.width * line2Head.transform(this.animationValue ?? 0.0f) - x2;
drawBar(x1, width1);
drawBar(x2, width2);
}
}
public override bool shouldRepaint(CustomPainter oldPainter) {
D.assert(oldPainter is _LinearProgressIndicatorPainter);
_LinearProgressIndicatorPainter painter = oldPainter as _LinearProgressIndicatorPainter;
return painter.backgroundColor != this.backgroundColor
|| painter.valueColor != this.valueColor
|| painter.value != this.value
|| painter.animationValue != this.animationValue;
}
}
public class LinearProgressIndicator : ProgressIndicator {
public LinearProgressIndicator(
Key key = null,
float? value = null,
Color backgroundColor = null,
Animation<Color> valueColor = null
) : base(
key: key,
value: value,
backgroundColor: backgroundColor,
valueColor: valueColor
) {
}
public override State createState() {
return new _LinearProgressIndicatorState();
}
}
class _LinearProgressIndicatorState : SingleTickerProviderStateMixin<LinearProgressIndicator> {
AnimationController _controller;
public _LinearProgressIndicatorState() {
}
public override void initState() {
base.initState();
this._controller = new AnimationController(
duration: new TimeSpan(0, 0, 0, 0, _ProgressIndicatorContants._kIndeterminateLinearDuration),
vsync: this
);
if (this.widget.value == null) {
this._controller.repeat();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
if (this.widget.value == null && !this._controller.isAnimating) {
this._controller.repeat();
}
else if (this.widget.value != null && this._controller.isAnimating) {
this._controller.stop();
}
}
public override void dispose() {
this._controller.dispose();
base.dispose();
}
Widget _buildIndicator(BuildContext context, float animationValue) {
return new Container(
constraints: new BoxConstraints(
minWidth: float.PositiveInfinity,
minHeight: _ProgressIndicatorContants._kLinearProgressIndicatorHeight
),
child: new CustomPaint(
painter: new _LinearProgressIndicatorPainter(
backgroundColor: this.widget._getBackgroundColor(context),
valueColor: this.widget._getValueColor(context),
value: this.widget.value,
animationValue: animationValue
)
)
);
}
public override Widget build(BuildContext context) {
if (this.widget.value != null) {
return this._buildIndicator(context, this._controller.value);
}
return new AnimatedBuilder(
animation: this._controller.view,
builder: (BuildContext _context, Widget child) => {
return this._buildIndicator(_context, this._controller.value);
}
);
}
}
class _CircularProgressIndicatorPainter : AbstractCustomPainter {
public _CircularProgressIndicatorPainter(
Color valueColor = null,
float? value = null,
float? headValue = null,
float? tailValue = null,
int? stepValue = null,
float? rotationValue = null,
float? strokeWidth = null
) {
this.valueColor = valueColor;
this.value = value;
this.headValue = headValue;
this.tailValue = tailValue;
this.stepValue = stepValue;
this.rotationValue = rotationValue;
this.strokeWidth = strokeWidth;
this.arcStart = value != null
? _startAngle
: _startAngle + tailValue * 3 / 2 * Mathf.PI + rotationValue * Mathf.PI * 1.7f -
stepValue * 0.8f * Mathf.PI;
this.arcSweep = value != null
? value.Value.clamp(0.0f, 1.0f) * _sweep
: Mathf.Max(headValue * 3 / 2 * Mathf.PI - tailValue * 3 / 2 * Mathf.PI ?? 0.0f, _epsilon);
}
public readonly Color valueColor;
public readonly float? value;
public readonly float? headValue;
public readonly float? tailValue;
public readonly int? stepValue;
public readonly float? rotationValue;
public readonly float? strokeWidth;
public readonly float? arcStart;
public readonly float? arcSweep;
const float _twoPi = Mathf.PI * 2.0f;
const float _epsilon = .001f;
const float _sweep = _twoPi - _epsilon;
const float _startAngle = -Mathf.PI / 2.0f;
public override void paint(Canvas canvas, Size size) {
Paint paint = new Paint();
paint.color = this.valueColor;
paint.strokeWidth = this.strokeWidth ?? 0.0f;
paint.style = PaintingStyle.stroke;
if (this.value == null)
{
paint.strokeCap = StrokeCap.square;
}
canvas.drawArc(Offset.zero & size, this.arcStart ?? 0.0f, this.arcSweep ?? 0.0f, false, paint);
}
public override bool shouldRepaint(CustomPainter oldPainter) {
D.assert(oldPainter is _CircularProgressIndicatorPainter);
_CircularProgressIndicatorPainter painter = oldPainter as _CircularProgressIndicatorPainter;
return painter.valueColor != this.valueColor
|| painter.value != this.value
|| painter.headValue != this.headValue
|| painter.tailValue != this.tailValue
|| painter.stepValue != this.stepValue
|| painter.rotationValue != this.rotationValue
|| painter.strokeWidth != this.strokeWidth;
}
}
public class CircularProgressIndicator : ProgressIndicator {
public CircularProgressIndicator(
Key key = null,
float? value = null,
Color backgroundColor = null,
Animation<Color> valueColor = null,
float strokeWidth = 4.0f
) : base(
key: key,
value: value,
backgroundColor: backgroundColor,
valueColor: valueColor
) {
this.strokeWidth = strokeWidth;
}
public readonly float? strokeWidth;
public override State createState() {
return new _CircularProgressIndicatorState();
}
}
class _CircularProgressIndicatorState : SingleTickerProviderStateMixin<CircularProgressIndicator> {
protected AnimationController _controller;
public _CircularProgressIndicatorState() {
}
public override void initState() {
base.initState();
this._controller = new AnimationController(
duration: new TimeSpan(0, 0, 0, 5),
vsync: this
);
if (this.widget.value == null) {
this._controller.repeat();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
if (this.widget.value == null && !this._controller.isAnimating) {
this._controller.repeat();
}
else if (this.widget.value != null && this._controller.isAnimating) {
this._controller.stop();
}
}
public override void dispose() {
this._controller.dispose();
base.dispose();
}
Widget _buildIndicator(BuildContext context, float headValue, float tailValue, int stepValue,
float rotationValue) {
return new Container(
constraints: new BoxConstraints(
minWidth: _ProgressIndicatorContants._kMinCircularProgressIndicatorSize,
minHeight: _ProgressIndicatorContants._kMinCircularProgressIndicatorSize
),
child: new CustomPaint(
painter: new _CircularProgressIndicatorPainter(
valueColor: this.widget._getValueColor(context),
value: this.widget.value,
headValue: headValue,
tailValue: tailValue,
stepValue: stepValue,
rotationValue: rotationValue,
strokeWidth: this.widget.strokeWidth
)
)
);
}
protected Widget _buildAnimation() {
return new AnimatedBuilder(
animation: this._controller,
builder: (BuildContext context, Widget child) => {
return this._buildIndicator(
context,
_ProgressIndicatorContants._kStrokeHeadTween.evaluate(this._controller),
_ProgressIndicatorContants._kStrokeTailTween.evaluate(this._controller),
_ProgressIndicatorContants._kStepTween.evaluate(this._controller),
_ProgressIndicatorContants._kRotationTween.evaluate(this._controller)
);
}
);
}
public override Widget build(BuildContext context) {
if (this.widget.value != null) {
return this._buildIndicator(context, 0.0f, 0.0f, 0, 0.0f);
}
return this._buildAnimation();
}
}
class _RefreshProgressIndicatorPainter : _CircularProgressIndicatorPainter {
public _RefreshProgressIndicatorPainter(
Color valueColor = null,
float? value = null,
float? headValue = null,
float? tailValue = null,
int? stepValue = null,
float? rotationValue = null,
float? strokeWidth = null,
float? arrowheadScale = null
) : base(
valueColor: valueColor,
value: value,
headValue: headValue,
tailValue: tailValue,
stepValue: stepValue,
rotationValue: rotationValue,
strokeWidth: strokeWidth
) {
this.arrowheadScale = arrowheadScale;
}
public readonly float? arrowheadScale;
void paintArrowhead(Canvas canvas, Size size) {
float arcEnd = this.arcStart + this.arcSweep ?? 0.0f;
float ux = Mathf.Cos(arcEnd);
float uy = Mathf.Sin(arcEnd);
D.assert(size.width == size.height);
float radius = size.width / 2.0f;
float? arrowheadPointX = radius + ux * radius + -uy * this.strokeWidth * 2.0f * this.arrowheadScale;
float? arrowheadPointY = radius + uy * radius + ux * this.strokeWidth * 2.0f * this.arrowheadScale;
float? arrowheadRadius = this.strokeWidth * 1.5f * this.arrowheadScale;
float? innerRadius = radius - arrowheadRadius;
float? outerRadius = radius + arrowheadRadius;
Path path = new Path();
path.moveTo(radius + ux * innerRadius ?? 0.0f, radius + uy * innerRadius ?? 0.0f);
path.lineTo(radius + ux * outerRadius ?? 0.0f, radius + uy * outerRadius ?? 0.0f);
path.lineTo(arrowheadPointX ?? 0.0f, arrowheadPointY ?? 0.0f);
path.close();
Paint paint = new Paint();
paint.color = this.valueColor;
paint.strokeWidth = this.strokeWidth ?? 0.0f;
paint.style = PaintingStyle.fill;
canvas.drawPath(path, paint);
}
public override void paint(Canvas canvas, Size size) {
base.paint(canvas, size);
if (this.arrowheadScale > 0.0) {
this.paintArrowhead(canvas, size);
}
}
}
public class RefreshProgressIndicator : CircularProgressIndicator {
public RefreshProgressIndicator(
Key key = null,
float? value = null,
Color backgroundColor = null,
Animation<Color> valueColor = null,
float strokeWidth = 2.0f
) : base(
key: key,
value: value,
backgroundColor: backgroundColor,
valueColor: valueColor,
strokeWidth: strokeWidth
) {
}
public override State createState() {
return new _RefreshProgressIndicatorState();
}
}
class _RefreshProgressIndicatorState : _CircularProgressIndicatorState {
const float _indicatorSize = 40.0f;
public _RefreshProgressIndicatorState() {
}
public override Widget build(BuildContext context) {
if (this.widget.value != null) {
this._controller.setValue(this.widget.value / 10.0f ?? 0.0f);
}
else if (!this._controller.isAnimating) {
this._controller.repeat();
}
return this._buildAnimation();
}
Widget _buildIndicator(BuildContext context, float headValue, float tailValue, int stepValue,
float rotationValue) {
float arrowheadScale =
this.widget.value == null ? 0.0f : (this.widget.value * 2.0f).Value.clamp(0.0f, 1.0f);
return new Container(
width: _indicatorSize,
height: _indicatorSize,
margin: EdgeInsets.all(4.0f),
child: new Material(
type: MaterialType.circle,
color: this.widget.backgroundColor ?? Theme.of(context).canvasColor,
elevation: 2.0f,
child: new Padding(
padding: EdgeInsets.all(12.0f),
child: new CustomPaint(
painter: new _RefreshProgressIndicatorPainter(
valueColor: this.widget._getValueColor(context),
value: null,
headValue: headValue,
tailValue: tailValue,
stepValue: stepValue,
rotationValue: rotationValue,
strokeWidth: this.widget.strokeWidth,
arrowheadScale: arrowheadScale
)
)
)
)
);
}
}
}

3
Runtime/material/progress_indicator.cs.meta


fileFormatVersion: 2
guid: 42b0b0b180624c38b2dec573a232bd8a
timeCreated: 1552530632

248
Runtime/widgets/form.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public class Form : StatefulWidget {
public Form(
Key key = null,
Widget child = null,
bool autovalidate = false,
WillPopCallback onWillPop = null,
VoidCallback onChanged = null
) : base(key: key) {
D.assert(child != null);
this.child = child;
this.autovalidate = autovalidate;
this.onWillPop = onWillPop;
this.onChanged = onChanged;
}
public static FormState of(BuildContext context) {
_FormScope scope = (_FormScope) context.inheritFromWidgetOfExactType(typeof(_FormScope));
return scope?._formState;
}
public readonly Widget child;
public readonly bool autovalidate;
public readonly WillPopCallback onWillPop;
public readonly VoidCallback onChanged;
public override State createState() {
return new FormState();
}
}
public class FormState : State<Form> {
int _generation = 0;
public readonly HashSet<FormFieldState<dynamic>> _fields = new HashSet<FormFieldState<dynamic>>();
public FormState() {
}
public void _fieldDidChange() {
if (this.widget.onChanged != null) {
this.widget.onChanged();
}
this._forceRebuild();
}
void _forceRebuild() {
this.setState(() => { ++this._generation; });
}
public void _register(FormFieldState<dynamic> field) {
this._fields.Add(field);
}
public void _unregister(FormFieldState<dynamic> field) {
this._fields.Remove(field);
}
public override Widget build(BuildContext context) {
if (this.widget.autovalidate) {
this._validate();
}
return new WillPopScope(
onWillPop: this.widget.onWillPop,
child: new _FormScope(
formState: this,
generation: this._generation,
child: this.widget.child
)
);
}
void save() {
foreach (FormFieldState<dynamic> field in this._fields) {
field.save();
}
}
void reset() {
foreach (FormFieldState<dynamic> field in this._fields) {
field.reset();
}
this._fieldDidChange();
}
bool validate() {
this._forceRebuild();
return this._validate();
}
bool _validate() {
bool hasError = false;
foreach (FormFieldState<dynamic> field in this._fields) {
hasError = !field.validate() || hasError;
}
return !hasError;
}
}
class _FormScope : InheritedWidget {
public _FormScope(
Key key = null,
Widget child = null,
FormState formState = null,
int? generation = null
) :
base(key: key, child: child) {
this._formState = formState;
this._generation = generation;
}
public readonly FormState _formState;
public readonly int? _generation;
public Form form {
get { return this._formState.widget; }
}
public override bool updateShouldNotify(InheritedWidget _old) {
_FormScope old = _old as _FormScope;
return this._generation != old._generation;
}
}
public delegate string FormFieldValidator<T>(T value);
public delegate void FormFieldSetter<T>(T newValue);
public delegate Widget FormFieldBuilder<T>(FormFieldState<T> field) where T : class;
public class FormField<T> : StatefulWidget where T : class {
public FormField(
Key key = null,
FormFieldBuilder<T> builder = null,
FormFieldSetter<T> onSaved = null,
FormFieldValidator<T> validator = null,
T initialValue = null,
bool autovalidate = false,
bool enabled = true
) : base(key: key) {
D.assert(builder != null);
this.onSaved = onSaved;
this.validator = validator;
this.builder = builder;
this.initialValue = initialValue;
this.autovalidate = autovalidate;
this.enabled = enabled;
}
public readonly FormFieldSetter<T> onSaved;
public readonly FormFieldValidator<T> validator;
public readonly FormFieldBuilder<T> builder;
public readonly T initialValue;
public readonly bool autovalidate;
public readonly bool enabled;
public override State createState() {
return new FormFieldState<T>();
}
}
public class FormFieldState<T> : State<FormField<T>> where T : class {
T _value;
string _errorText;
public T value {
get { return this._value; }
}
public string errorText {
get { return this._errorText; }
}
public bool hasError {
get { return this._errorText != null; }
}
public void save() {
if (this.widget.onSaved != null) {
this.widget.onSaved(this.value);
}
}
public void reset() {
this.setState(() => {
this._value = this.widget.initialValue;
this._errorText = null;
});
}
public bool validate() {
this.setState(() => { this._validate(); });
return !this.hasError;
}
bool _validate() {
if (this.widget.validator != null) {
this._errorText = this.widget.validator(this._value);
}
return !this.hasError;
}
public virtual void didChange(T value) {
this.setState(() => { this._value = value; });
Form.of(this.context)?._fieldDidChange();
}
protected void setValue(T value) {
this._value = value;
}
public override void initState() {
base.initState();
this._value = this.widget.initialValue;
}
public override void deactivate() {
Form.of(this.context)?._unregister(this as FormFieldState<dynamic>);
base.deactivate();
}
public override Widget build(BuildContext context) {
if (this.widget.autovalidate && this.widget.enabled) {
this._validate();
}
Form.of(context)?._register(this as FormFieldState<dynamic>);
return this.widget.builder(this);
}
}
}

3
Runtime/widgets/form.cs.meta


fileFormatVersion: 2
guid: 3ce8dad5676b40ec862b142dd03b9f64
timeCreated: 1552545243

69
Runtime/widgets/will_pop_scope.cs


using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.widgets {
public class WillPopScope : StatefulWidget {
public WillPopScope(
Key key = null,
Widget child = null,
WillPopCallback onWillPop = null
) : base(key: key) {
D.assert(child != null);
this.onWillPop = onWillPop;
this.child = child;
}
public readonly Widget child;
public readonly WillPopCallback onWillPop;
public override State createState() {
return new _WillPopScopeState();
}
}
class _WillPopScopeState : State<WillPopScope> {
ModalRoute _route;
public _WillPopScopeState() {
}
public override void didChangeDependencies() {
base.didChangeDependencies();
if (this.widget.onWillPop != null) {
this._route?.removeScopedWillPopCallback(this.widget.onWillPop);
}
this._route = ModalRoute.of(this.context);
if (this.widget.onWillPop != null) {
this._route?.addScopedWillPopCallback(this.widget.onWillPop);
}
}
public override void didUpdateWidget(StatefulWidget _oldWidget) {
base.didUpdateWidget(_oldWidget);
D.assert(this._route == ModalRoute.of(this.context));
WillPopScope oldWidget = _oldWidget as WillPopScope;
if (this.widget.onWillPop != oldWidget.onWillPop && this._route != null) {
if (oldWidget.onWillPop != null) {
this._route.removeScopedWillPopCallback(oldWidget.onWillPop);
}
if (this.widget.onWillPop != null) {
this._route.addScopedWillPopCallback(this.widget.onWillPop);
}
}
}
public override void dispose() {
if (this.widget.onWillPop != null) {
this._route?.removeScopedWillPopCallback(this.widget.onWillPop);
}
base.dispose();
}
public override Widget build(BuildContext context) {
return this.widget.child;
}
}
}

3
Runtime/widgets/will_pop_scope.cs.meta


fileFormatVersion: 2
guid: 624e6292cdfc4b43ac439df81ae8efee
timeCreated: 1552547854

8
Tests/Editor/demo_charts.meta


fileFormatVersion: 2
guid: 16325b3157a5144c789848b8ecc53311
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

149
Tests/Editor/demo_charts/bar.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
namespace UIWidgets.Tests.demo_charts {
public class BarChart {
public BarChart(List<Bar> bars) {
this.bars = bars;
}
public static BarChart empty() {
return new BarChart(new List<Bar>());
}
public static BarChart random(Size size) {
var barWidthFraction = 0.75f;
var ranks = selectRanks(ColorPalette.primary.length);
var barCount = ranks.Count;
var barDistance = size.width / (1 + barCount);
var barWidth = barDistance * barWidthFraction;
var startX = barDistance - barWidth / 2;
var bars = Enumerable.Range(0, barCount).Select(i => new Bar(
ranks[i],
startX + i * barDistance,
barWidth,
Random.value * size.height,
ColorPalette.primary[ranks[i]]
)).ToList();
return new BarChart(bars);
}
static List<int> selectRanks(int cap) {
var ranks = new List<int>();
var rank = 0;
while (true) {
if (Random.value < 0.2f) {
rank++;
}
if (cap <= rank) {
break;
}
ranks.Add(rank);
rank++;
}
return ranks;
}
public readonly List<Bar> bars;
}
public class BarChartTween : Tween<BarChart> {
readonly MergeTween<Bar> _barsTween;
public BarChartTween(BarChart begin, BarChart end) : base(begin: begin, end: end) {
this._barsTween = new MergeTween<Bar>(begin.bars, end.bars);
}
public override BarChart lerp(float t) {
return new BarChart(this._barsTween.lerp(t));
}
}
public class Bar : MergeTweenable<Bar> {
public Bar(int rank, float x, float width, float height, Color color) {
this.rank = rank;
this.x = x;
this.width = width;
this.height = height;
this.color = color;
}
public readonly int rank;
public readonly float x;
public readonly float width;
public readonly float height;
public readonly Color color;
public Bar empty {
get { return new Bar(this.rank, this.x, 0.0f, 0.0f, this.color); }
}
public bool less(Bar other) {
return this.rank < other.rank;
}
public Tween<Bar> tweenTo(Bar other) {
return new BarTween(this, other);
}
public static Bar lerp(Bar begin, Bar end, float t) {
D.assert(begin.rank == end.rank);
return new Bar(
begin.rank,
MathUtils.lerpFloat(begin.x, end.x, t),
MathUtils.lerpFloat(begin.width, end.width, t),
MathUtils.lerpFloat(begin.height, end.height, t),
Color.lerp(begin.color, end.color, t)
);
}
}
public class BarTween : Tween<Bar> {
public BarTween(Bar begin, Bar end) : base(begin: begin, end: end) {
D.assert(begin.rank == end.rank);
}
public override Bar lerp(float t) {
return Bar.lerp(this.begin, this.end, t);
}
}
public class BarChartPainter : AbstractCustomPainter {
public BarChartPainter(Animation<BarChart> animation)
: base(repaint: animation) {
this.animation = animation;
}
public readonly Animation<BarChart> animation;
public override void paint(Canvas canvas, Size size) {
var paint = new Paint();
paint.style = PaintingStyle.fill;
var chart = this.animation.value;
foreach (var bar in chart.bars) {
paint.color = bar.color;
canvas.drawRect(
Rect.fromLTWH(
bar.x,
size.height - bar.height,
bar.width,
bar.height
),
paint
);
}
}
public override bool shouldRepaint(CustomPainter old) {
return false;
}
}
}

11
Tests/Editor/demo_charts/bar.cs.meta


fileFormatVersion: 2
guid: 20c43f616dd7640279364f93d965f4c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

38
Tests/Editor/demo_charts/color_palette.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
namespace UIWidgets.Tests.demo_charts {
public class ColorPalette {
public static readonly ColorPalette primary = new ColorPalette(new List<Color> {
Colors.blue[400],
Colors.red[400],
Colors.green[400],
Colors.yellow[400],
Colors.purple[400],
Colors.orange[400],
Colors.teal[400]
});
public ColorPalette(List<Color> colors) {
D.assert(colors.isNotEmpty);
this._colors = colors;
}
readonly List<Color> _colors;
public Color this[int index] {
get { return this._colors[index % this.length]; }
}
public int length {
get { return this._colors.Count; }
}
public Color random() {
return this[Random.Range(0, this.length - 1)];
}
}
}

11
Tests/Editor/demo_charts/color_palette.cs.meta


fileFormatVersion: 2
guid: f9e9e9f9c5ecd474b8ef6a194f2d9fc7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

67
Tests/Editor/demo_charts/main.cs


using System;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace UIWidgets.Tests.demo_charts {
/***
* from https://github.com/mravn/charts
*/
public class ChartPage : StatefulWidget {
public override State createState() {
return new ChartPageState();
}
}
public class ChartPageState : TickerProviderStateMixin<ChartPage> {
public static readonly Size size = new Size(200.0f, 100.0f);
AnimationController _animation;
BarChartTween _tween;
public override
void initState() {
base.initState();
this._animation = new AnimationController(
duration: new TimeSpan(0, 0, 0, 0, 300),
vsync: this
);
this._tween = new BarChartTween(
BarChart.empty(),
BarChart.random(size)
);
this._animation.forward();
}
public override void dispose() {
this._animation.dispose();
base.dispose();
}
void changeData() {
this.setState(() => {
this._tween = new BarChartTween(
this._tween.evaluate(this._animation),
BarChart.random(size)
);
this._animation.forward(from: 0.0f);
});
}
public override Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new CustomPaint(
size: size,
painter: new BarChartPainter(this._tween.animate(this._animation))
)
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Unity.UIWidgets.material.Icons.refresh),
onPressed: this.changeData
)
);
}
}
}

11
Tests/Editor/demo_charts/main.cs.meta


fileFormatVersion: 2
guid: 905d6da1ea7b947be937556edda2b664
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

41
Tests/Editor/demo_charts/tween.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.animation;
namespace UIWidgets.Tests.demo_charts {
public interface MergeTweenable<T> {
T empty { get; }
Tween<T> tweenTo(T other);
bool less(T other);
}
public class MergeTween<T> : Tween<List<T>> where T : MergeTweenable<T> {
public MergeTween(List<T> begin, List<T> end) : base(begin: begin, end: end) {
int bMax = begin.Count;
int eMax = end.Count;
var b = 0;
var e = 0;
while (b + e < bMax + eMax) {
if (b < bMax && (e == eMax || begin[b].less(end[e]))) {
this._tweens.Add(begin[b].tweenTo(begin[b].empty));
b++;
} else if (e < eMax && (b == bMax || end[e].less(begin[b]))) {
this._tweens.Add(end[e].empty.tweenTo(end[e]));
e++;
} else {
this._tweens.Add(begin[b].tweenTo(end[e]));
b++;
e++;
}
}
}
readonly List<Tween<T>> _tweens = new List<Tween<T>>();
public override List<T> lerp(float t) {
return Enumerable.Range(0, this._tweens.Count).Select(i => this._tweens[i].lerp(t)).ToList();
}
}
}

11
Tests/Editor/demo_charts/tween.cs.meta


fileFormatVersion: 2
guid: ae95c92eb6d8346f3bbc89a91d9e191d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存