浏览代码

Merge pull request #273 from UnityTech/yczhang1.5.4

[To 1.5.4] Finish src/widgets.
/main
GitHub 5 年前
当前提交
d828a18f
共有 56 个文件被更改,包括 1915 次插入621 次删除
  1. 2
      Runtime/gestures/binding.cs
  2. 160
      Runtime/gestures/long_press.cs
  3. 7
      Runtime/material/app.cs
  4. 68
      Runtime/material/text_field.cs
  5. 2
      Runtime/material/text_form_field.cs
  6. 7
      Runtime/painting/box_border.cs
  7. 26
      Runtime/painting/decoration_image.cs
  8. 98
      Runtime/painting/gradient.cs
  9. 26
      Runtime/painting/image_stream.cs
  10. 20
      Runtime/painting/notched_shapes.cs
  11. 90
      Runtime/painting/text_painter.cs
  12. 192
      Runtime/painting/text_style.cs
  13. 1
      Runtime/rendering/binding.cs
  14. 4
      Runtime/rendering/box.cs
  15. 129
      Runtime/rendering/editable.cs
  16. 2
      Runtime/rendering/error.cs
  17. 5
      Runtime/rendering/flex.cs
  18. 164
      Runtime/rendering/layer.cs
  19. 9
      Runtime/rendering/object.cs
  20. 45
      Runtime/rendering/paragraph.cs
  21. 104
      Runtime/rendering/proxy_box.cs
  22. 3
      Runtime/rendering/sliver.cs
  23. 3
      Runtime/rendering/sliver_grid.cs
  24. 2
      Runtime/rendering/sliver_list.cs
  25. 240
      Runtime/ui/painting/path.cs
  26. 23
      Runtime/ui/painting/txt/font_manager.cs
  27. 6
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs
  28. 18
      Runtime/ui/text.cs
  29. 6
      Runtime/ui/txt/paragraph.cs
  30. 7
      Runtime/ui/window.cs
  31. 16
      Runtime/widgets/basic.cs
  32. 2
      Runtime/widgets/dismissible.cs
  33. 77
      Runtime/widgets/editable_text.cs
  34. 10
      Runtime/widgets/fade_in_image.cs
  35. 4
      Runtime/widgets/form.cs
  36. 53
      Runtime/widgets/gesture_detector.cs
  37. 79
      Runtime/widgets/heroes.cs
  38. 2
      Runtime/widgets/icon.cs
  39. 4
      Runtime/widgets/nested_scroll_view.cs
  40. 83
      Runtime/widgets/overlay.cs
  41. 7
      Runtime/widgets/page_view.cs
  42. 6
      Runtime/widgets/routes.cs
  43. 26
      Runtime/widgets/scroll_view.cs
  44. 39
      Runtime/widgets/scrollable.cs
  45. 2
      Runtime/widgets/single_child_scroll_view.cs
  46. 13
      Runtime/widgets/text.cs
  47. 179
      Runtime/widgets/text_selection.cs
  48. 6
      Samples/UIWidgetSample/LongPressSample.cs
  49. 36
      Samples/UIWidgetSample/TextInputSample.cs
  50. 5
      Tests/Editor/Paragraph.cs
  51. 160
      Runtime/painting/continuous_rectangle_border.cs
  52. 11
      Runtime/painting/continuous_rectangle_border.cs.meta
  53. 220
      Runtime/painting/strut_style.cs
  54. 11
      Runtime/painting/strut_style.cs.meta
  55. 5
      Runtime/rendering/debug.cs
  56. 11
      Runtime/rendering/debug.cs.meta

2
Runtime/gestures/binding.cs


}
HitTestResult hitTestResult = null;
if (evt is PointerDownEvent || evt is PointerSignalResolver) {
if (evt is PointerDownEvent || evt is PointerSignalEvent) {
D.assert(!this._hitTests.ContainsKey(evt.pointer));
hitTestResult = new HitTestResult();
this.hitTest(hitTestResult, evt.position);

160
Runtime/gestures/long_press.cs


public delegate void GestureLongPressUpCallback();
public delegate void GestureLongPressDragStartCallback(GestureLongPressDragStartDetails details);
public delegate void GestureLongPressStartCallback(LongPressStartDetails details);
public delegate void GestureLongPressDragUpdateCallback(GestureLongPressDragUpdateDetails details);
public delegate void GestureLongPressMoveUpdateCallback(LongPressMoveUpdateDetails details);
public delegate void GestureLongPressDragUpCallback(GestureLongPressDragUpDetails details);
public delegate void GestureLongPressEndCallback(LongPressEndDetails details);
public class GestureLongPressDragStartDetails {
public GestureLongPressDragStartDetails(
TimeSpan? sourceTimeStamp = null,
public class LongPressStartDetails {
public LongPressStartDetails(
this.sourceTimeStamp = sourceTimeStamp;
public readonly TimeSpan? sourceTimeStamp;
public class GestureLongPressDragUpdateDetails {
public GestureLongPressDragUpdateDetails(
TimeSpan? sourceTimeStamp = null,
public class LongPressMoveUpdateDetails {
public LongPressMoveUpdateDetails(
this.sourceTimeStamp = sourceTimeStamp;
public readonly TimeSpan? sourceTimeStamp;
public readonly Offset globalPosition;

public class GestureLongPressDragUpDetails {
public GestureLongPressDragUpDetails(
TimeSpan? sourceTimeStamp = null,
public class LongPressEndDetails {
public LongPressEndDetails(
this.sourceTimeStamp = sourceTimeStamp;
public readonly TimeSpan? sourceTimeStamp;
public LongPressGestureRecognizer(object debugOwner = null, PointerDeviceKind? kind = null) :
base(deadline: Constants.kLongPressTimeout, debugOwner: debugOwner, kind: kind) {
}
public LongPressGestureRecognizer(
float? postAcceptSlopTolerance = null,
object debugOwner = null,
PointerDeviceKind? kind = null) : base(
deadline: Constants.kLongPressTimeout,
postAcceptSlopTolerance: postAcceptSlopTolerance,
kind: kind,
debugOwner: debugOwner) { }
Offset _longPressOrigin;
public GestureLongPressStartCallback onLongPressStart;
public GestureLongPressMoveUpdateCallback onLongPressMoveUpdate;
public GestureLongPressEndCallback onLongPressEnd;
base.acceptGesture(this.primaryPointer);
if (this.onLongPress != null) {
this.invokeCallback<object>("onLongPress", () => {
this.onLongPress();

}
protected override void handlePrimaryPointer(PointerEvent evt) {
if (evt is PointerUpEvent) {
if (this._longPressAccepted && this.onLongPressUp != null) {
this._longPressAccepted = false;
this.invokeCallback<object>("onLongPressUp", () => {
this.onLongPressUp();
if (this.onLongPressStart != null) {
this.invokeCallback<object>("onLongPressStart",
() => {
this.onLongPressStart(new LongPressStartDetails(globalPosition: this._longPressOrigin));
}
else {
this.resolve(GestureDisposition.rejected);
}
}
else if (evt is PointerDownEvent || evt is PointerCancelEvent) {
this._longPressAccepted = false;
public override string debugDescription {
get { return "long press"; }
}
}
public class LongPressDragGestureRecognizer : PrimaryPointerGestureRecognizer {
public LongPressDragGestureRecognizer(object debugOwner = null) : base(
deadline: Constants.kLongPressTimeout,
postAcceptSlopTolerance: null,
debugOwner: debugOwner
) {
}
bool _longPressAccepted = false;
Offset _longPressOrigin;
TimeSpan? _longPressStartTimestamp;
public GestureLongPressDragStartCallback onLongPressStart;
public GestureLongPressDragUpdateCallback onLongPressDragUpdate;
public GestureLongPressDragUpCallback onLongPressUp;
protected override void handlePrimaryPointer(PointerEvent evt) {
if (evt is PointerUpEvent) {
if (this._longPressAccepted) {
if (this.onLongPressUp != null) {
this.invokeCallback<object>("onLongPressUp", () => {
this.onLongPressUp();
return null;
});
}
protected override void didExceedDeadline() {
this.resolve(GestureDisposition.accepted);
this._longPressAccepted = true;
base.acceptGesture(this.primaryPointer);
if (this.onLongPressStart != null) {
this.invokeCallback<object>("onLongPressStart", () => {
this.onLongPressStart(new GestureLongPressDragStartDetails(
sourceTimeStamp: this._longPressStartTimestamp,
globalPosition: this._longPressOrigin
));
return null;
});
}
}
if (this.onLongPressEnd != null) {
this.invokeCallback<object>("onLongPressEnd", () => {
this.onLongPressEnd(new LongPressEndDetails(globalPosition: evt.position));
return null;
});
}
protected override void handlePrimaryPointer(PointerEvent e) {
if (e is PointerUpEvent) {
if (this._longPressAccepted == true && this.onLongPressUp != null) {
this._longPressAccepted = false;
this.invokeCallback<object>("onLongPressUp", () => {
this.onLongPressUp(new GestureLongPressDragUpDetails(
sourceTimeStamp: e.timeStamp,
globalPosition: e.position
));
return null;
});
this._longPressAccepted = true;
else if (e is PointerDownEvent) {
else if (evt is PointerDownEvent || evt is PointerCancelEvent) {
this._longPressStartTimestamp = e.timeStamp;
this._longPressOrigin = e.position;
this._longPressOrigin = evt.position;
else if (e is PointerMoveEvent && this._longPressAccepted && this.onLongPressDragUpdate != null) {
this.invokeCallback<object>("onLongPressDrag", () => {
this.onLongPressDragUpdate(new GestureLongPressDragUpdateDetails(
sourceTimeStamp: e.timeStamp,
globalPosition: e.position,
offsetFromOrigin: e.position - this._longPressOrigin
else if (evt is PointerMoveEvent && this._longPressAccepted && this.onLongPressMoveUpdate != null) {
this.invokeCallback<object>("onLongPressMoveUpdate", () => {
this.onLongPressMoveUpdate(new LongPressMoveUpdateDetails(
globalPosition: evt.position,
offsetFromOrigin: evt.position - this._longPressOrigin
));
return null;
});

public override void acceptGesture(int pointer) {
}
protected override void didStopTrackingLastPointer(int pointer) {
this._longPressAccepted = false;
this._longPressOrigin = null;
this._longPressStartTimestamp = null;
base.didStopTrackingLastPointer(pointer);
}
get { return "long press drag"; }
get { return "long press"; }
}
}
}

7
Runtime/material/app.cs


class _MaterialAppState : State<MaterialApp> {
HeroController _heroController;
this._heroController = new HeroController(createRectTween: this._createRectTween);
if (this.widget.navigatorKey != (oldWidget as MaterialApp).navigatorKey) {
this._heroController = new HeroController(createRectTween: this._createRectTween);
}
this._updateNavigator();
}

this.widget.onGenerateRoute != null ||
this.widget.onUnknownRoute != null) {
this._navigatorObservers = new List<NavigatorObserver>(this.widget.navigatorObservers);
this._navigatorObservers.Add(this._heroController);
}
else {
this._navigatorObservers = null;

68
Runtime/material/text_field.cs


using System.Collections.Generic;
using System.Text;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;

InputDecoration decoration = null, bool noDecoration = false, TextInputType keyboardType = null,
TextInputAction? textInputAction = null,
TextCapitalization textCapitalization = TextCapitalization.none, TextStyle style = null,
StrutStyle strutStyle = null,
TextAlign textAlign = TextAlign.left, TextDirection textDirection = TextDirection.ltr,
bool autofocus = false, bool obscureText = false, bool autocorrect = false, int? maxLines = 1,
int? maxLength = null, bool maxLengthEnforced = true, ValueChanged<string> onChanged = null,

this.textInputAction = textInputAction;
this.textCapitalization = textCapitalization;
this.style = style;
this.strutStyle = strutStyle;
this.textAlign = textAlign;
this.textDirection = textDirection;
this.autofocus = autofocus;

public readonly TextCapitalization textCapitalization;
public readonly TextStyle style;
public readonly StrutStyle strutStyle;
public readonly TextAlign textAlign;

this._cancelCurrentSplash();
}
void _handleLongPress() {
if (this.widget.enableInteractiveSelection == true) {
this._renderEditable.handleLongPress();
void _handleSingleLongTapStart(LongPressStartDetails details) {
if (this.widget.selectionEnabled) {
switch (Theme.of(this.context).platform) {
case RuntimePlatform.IPhonePlayer:
this._renderEditable.selectPositionAt(
from: details.globalPosition,
cause: SelectionChangedCause.longPress
);
break;
case RuntimePlatform.Android:
this._renderEditable.selectWord(cause: SelectionChangedCause.longPress);
Feedback.forLongPress(this.context);
break;
}
void _handleDragSelectionStart(DragStartDetails details) {
void _handleSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) {
if (this.widget.selectionEnabled) {
switch (Theme.of(this.context).platform) {
case RuntimePlatform.IPhonePlayer:
this._renderEditable.selectPositionAt(
from: details.globalPosition,
cause: SelectionChangedCause.longPress
);
break;
case RuntimePlatform.Android:
this._renderEditable.selectWordsInRange(
from: details.globalPosition - details.offsetFromOrigin,
to: details.globalPosition,
cause: SelectionChangedCause.longPress);
Feedback.forLongPress(this.context);
break;
}
}
}
void _handleSingleLongTapEnd(LongPressEndDetails details) {
this._editableTextKey.currentState.showToolbar();
}
void _handleDoubleTapDown(TapDownDetails details) {
if (this.widget.selectionEnabled) {
this._renderEditable.selectWord(cause: SelectionChangedCause.doubleTap);
this._editableTextKey.currentState.showToolbar();
}
}
void _handleMouseDragSelectionStart(DragStartDetails details) {
this._renderEditable.selectPositionAt(
from: details.globalPosition,
cause: SelectionChangedCause.drag);

void _handleDragSelectionUpdate(DragStartDetails startDetails,
void _handleMouseDragSelectionUpdate(DragStartDetails startDetails,
DragUpdateDetails updateDetails) {
this._renderEditable.selectPositionAt(
from: startDetails.globalPosition,

textInputAction: this.widget.textInputAction,
textCapitalization: this.widget.textCapitalization,
style: style,
strutStyle: this.widget.strutStyle,
textAlign: this.widget.textAlign,
textDirection: this.widget.textDirection,
autofocus: this.widget.autofocus,

// onForcePressStart: forcePressEnabled ? this._handleForcePressStarted : null, // TODO: Remove this when force press is added
onSingleTapUp: this._handleSingleTapUp,
onSingleTapCancel: this._handleSingleTapCancel,
onSingleLongTapStart: this._handleLongPress,
onDragSelectionStart: this._handleDragSelectionStart,
onDragSelectionUpdate: this._handleDragSelectionUpdate,
onSingleLongTapStart: this._handleSingleLongTapStart,
onSingleLongTapMoveUpdate: this._handleSingleLongTapMoveUpdate,
onSingleLongTapEnd: this._handleSingleLongTapEnd,
onDoubleTapDown: this._handleDoubleTapDown,
onDragSelectionStart: this._handleMouseDragSelectionStart,
onDragSelectionUpdate: this._handleMouseDragSelectionUpdate,
behavior: HitTestBehavior.translucent,
child: child
)

2
Runtime/material/text_form_field.cs


TextCapitalization textCapitalization = TextCapitalization.none,
TextInputAction? textInputAction = null,
TextStyle style = null,
StrutStyle strutStyle = null,
TextDirection? textDirection = null,
TextAlign textAlign = TextAlign.left,
bool autofocus = false,

keyboardType: keyboardType,
textInputAction: textInputAction,
style: style,
strutStyle: strutStyle,
textAlign: textAlign,
textDirection: textDirection ?? TextDirection.ltr,
textCapitalization: textCapitalization,

7
Runtime/painting/box_border.cs


this.left = left ?? BorderSide.none;
}
public static Border fromBorderSide(BorderSide side) {
D.assert(side != null);
return new Border(top: side, right: side, bottom: side, left: side);
}
public static Border all(
Color color = null,
float width = 1.0f,

return new Border(top: side, right: side, bottom: side, left: side);
return Border.fromBorderSide(side);
}
public static Border merge(Border a, Border b) {

26
Runtime/painting/decoration_image.cs


outputSize += sliceBorder;
destinationSize += sliceBorder;
D.assert(sourceSize == inputSize,
() => $"centerSlice was used with a BoxFit {fit} that does not guarantee that the image is fully visible.");
() =>
$"centerSlice was used with a BoxFit {fit} that does not guarantee that the image is fully visible.");
}
if (repeat != ImageRepeat.noRepeat && destinationSize == outputSize) {

Rect sourceRect = alignment.inscribe(
sourceSize, Offset.zero & inputSize
);
foreach (Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageRect(image, sourceRect, tileRect, paint);
if (repeat == ImageRepeat.noRepeat) {
canvas.drawImageRect(image, sourceRect, destinationRect, paint);
}
else {
foreach (Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageRect(image, sourceRect, tileRect, paint);
}
foreach (Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageNine(image, centerSlice, tileRect, paint);
if (repeat == ImageRepeat.noRepeat) {
canvas.drawImageNine(image, centerSlice, destinationRect, paint);
}
else {
foreach (Rect tileRect in _generateImageTileRects(rect, destinationRect, repeat)) {
canvas.drawImageNine(image, centerSlice, tileRect, paint);
}
}
}

static IEnumerable<Rect> _generateImageTileRects(Rect outputRect, Rect fundamentalRect,
ImageRepeat repeat) {
if (repeat == ImageRepeat.noRepeat) {
yield return fundamentalRect;
yield break;
}
int startX = 0;
int startY = 0;
int stopX = 0;

98
Runtime/painting/gradient.cs


public readonly List<Color> colors;
public readonly List<float> stops;
public static _ColorsAndStops _interpolateColorsAndStops(
List<Color> aColors, List<float> aStops, List<Color> bColors, List<float> bStops, float t) {
D.assert(aColors.Count == bColors.Count,
() => "Cannot interpolate between two gradients with a different number of colors.");
D.assert((aStops == null && aColors.Count == 2) || (aStops != null && aStops.Count == aColors.Count));
D.assert((bStops == null && bColors.Count == 2) || (bStops != null && bStops.Count == bColors.Count));
List<Color> interpolatedColors = new List<Color>();
static Color _sample(List<Color> colors, List<float> stops, float t) {
D.assert(colors != null);
D.assert(colors.isNotEmpty);
D.assert(stops != null);
D.assert(stops.isNotEmpty);
if (t < stops.first()) {
return colors.first();
}
for (int i = 0; i < aColors.Count; i += 1) {
interpolatedColors.Add(Color.lerp(aColors[i], bColors[i], t));
if (t < stops.last()) {
return colors.last();
List<float> interpolatedStops = null;
if (aStops != null || bStops != null) {
aStops = aStops ?? new List<float> {0.0f, 1.0f};
bStops = bStops ?? new List<float> {0.0f, 1.0f};
int index = stops.FindLastIndex((float s) => { return s <= t; });
D.assert(index != -1);
return Color.lerp(colors[index], colors[index + 1],
(t - stops[index]) / (stops[index + 1] - stops[index]));
}
D.assert(aStops.Count == bStops.Count);
interpolatedStops = new List<float>();
for (int i = 0; i < aStops.Count; i += 1) {
interpolatedStops.Add(MathUtils.lerpFloat(aStops[i], bStops[i], t).clamp(0.0f, 1.0f));
}
}
internal static _ColorsAndStops _interpolateColorsAndStops(
List<Color> aColors,
List<float> aStops,
List<Color> bColors,
List<float> bStops,
float t) {
D.assert(aColors.Count >= 2);
D.assert(bColors.Count >= 2);
D.assert(aStops.Count == aColors.Count);
D.assert(bStops.Count == bColors.Count);
SplayTree<float, bool> stops = new SplayTree<float, bool>();
stops.AddAll(aStops);
stops.AddAll(bStops);
List<float> interpolatedStops = stops.Keys.ToList();
List<Color> interpolatedColors = interpolatedStops.Select<float, Color>((float stop) => {
return Color.lerp(_sample(aColors, aStops, stop), _sample(bColors, bStops, stop), t);
}).ToList();
return new _ColorsAndStops(interpolatedColors, interpolatedStops);
}

protected List<float> _impliedStops() {
if (this.stops != null) {
return this.stops;
}
if (this.colors.Count == 2) {
return null;
}
D.assert(this.colors.Count >= 2, () => "colors list must have at least two colors");

}
protected override Gradient lerpFrom(Gradient a, float t) {
if (a == null || (a is LinearGradient && a.colors.Count == this.colors.Count)) {
return LinearGradient.lerp((LinearGradient) a, this, t);
if (a == null || (a is LinearGradient)) {
return lerp((LinearGradient) a, this, t);
}
return base.lerpFrom(a, t);

if (b == null || (b is LinearGradient && b.colors.Count == this.colors.Count)) {
return LinearGradient.lerp(this, (LinearGradient) b, t);
if (b == null || (b is LinearGradient)) {
return lerp(this, (LinearGradient) b, t);
}
return base.lerpTo(b, t);

return (LinearGradient) a.scale(1.0f - t);
}
_ColorsAndStops interpolated =
_ColorsAndStops._interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t);
_ColorsAndStops interpolated = _ColorsAndStops._interpolateColorsAndStops(
a.colors,
a._impliedStops(),
b.colors,
b._impliedStops(),
t);
return new LinearGradient(
begin: Alignment.lerp(a.begin, b.begin, t),
end: Alignment.lerp(a.end, b.end, t),

return !Equals(left, right);
}
public override String ToString() {
public override string ToString() {
return $"{this.GetType()}({this.begin}, {this.end}," +
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})";
}

}
protected override Gradient lerpFrom(Gradient a, float t) {
if (a == null || (a is RadialGradient && a.colors.Count == this.colors.Count)) {
return RadialGradient.lerp((RadialGradient) a, this, t);
if (a == null || (a is RadialGradient)) {
return lerp((RadialGradient) a, this, t);
}
return base.lerpFrom(a, t);

if (b == null || (b is RadialGradient && b.colors.Count == this.colors.Count)) {
return RadialGradient.lerp(this, (RadialGradient) b, t);
if (b == null || (b is RadialGradient)) {
return lerp(this, (RadialGradient) b, t);
}
return base.lerpTo(b, t);

return (RadialGradient) a.scale(1.0f - t);
}
_ColorsAndStops interpolated =
_ColorsAndStops._interpolateColorsAndStops(a.colors, a.stops, b.colors, b.stops, t);
_ColorsAndStops interpolated = _ColorsAndStops._interpolateColorsAndStops(
a.colors,
a._impliedStops(),
b.colors,
b._impliedStops(),
t);
return new RadialGradient(
center: Alignment.lerp(a.center, b.center, t),
radius: Mathf.Max(0.0f, MathUtils.lerpFloat(a.radius, b.radius, t)),

return !Equals(left, right);
}
public override String ToString() {
public override string ToString() {
return $"{this.GetType()}({this.center}, {this.radius}," +
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})";
}

protected override Gradient lerpFrom(Gradient a, float t) {
if (a == null || (a is SweepGradient && a.colors.Count == this.colors.Count)) {
return SweepGradient.lerp((SweepGradient) a, this, t);
return lerp((SweepGradient) a, this, t);
}
return base.lerpFrom(a, t);

return !Equals(left, right);
}
public override String ToString() {
public override string ToString() {
return $"{this.GetType()}({this.center}, {this.startAngle}, {this.endAngle}, " +
$"{this.colors.toStringList()}, {this.stops.toStringList()}, {this.tileMode})";
}

26
Runtime/painting/image_stream.cs


new UIWidgetsErrorDetails(
exception: ex,
library: "image resource service",
context: "by a synchronously-called image error listener"
context: "when reporting an error to an image listener"
)
);
}

this._scale = scale;
this._informationCollector = informationCollector;
this._framesEmitted = 0;
this._timer = null;
codec.Then((Action<Codec>) this._handleCodecReady, ex => {
this.reportError(
context: "resolving an image codec",

FrameInfo _nextFrame;
TimeSpan? _shownTimestamp;
TimeSpan? _frameDuration;
int _framesEmitted;
int _framesEmitted = 0;
bool _frameCallbackScheduled = false;
this._decodeNextFrameAndSchedule();
if (this.hasListeners) {
this._decodeNextFrameAndSchedule();
}
this._frameCallbackScheduled = false;
if (!this.hasListeners) {
return;
}

TimeSpan delay = this._frameDuration.Value - (timestamp - this._shownTimestamp.Value);
delay = new TimeSpan((long) (delay.Ticks * SchedulerBinding.instance.timeDilation));
this._timer = Window.instance.run(delay,
() => { SchedulerBinding.instance.scheduleFrameCallback(this._handleAppFrame); });
this._timer = Window.instance.run(delay, this._scheduleAppFrame);
}
bool _isFirstFrame() {

return;
}
this._scheduleAppFrame();
}
void _scheduleAppFrame() {
if (this._frameCallbackScheduled) {
return;
}
this._frameCallbackScheduled = true;
SchedulerBinding.instance.scheduleFrameCallback(this._handleAppFrame);
}

20
Runtime/painting/notched_shapes.cs


return ret;
}
}
class AutomaticNotchedShape : NotchedShape {
public AutomaticNotchedShape(ShapeBorder host, ShapeBorder guest = null) {
this.host = host;
this.guest = guest;
}
public readonly ShapeBorder host;
public readonly ShapeBorder guest;
public override Path getOuterPath(Rect hostRect, Rect guestRect) {
Path hostPath = this.host.getOuterPath(hostRect);
if (this.guest != null && guestRect != null) {
Path guestPath = this.guest.getOuterPath(guestRect);
return Path.combine(PathOperation.difference, hostPath, guestPath);
}
return hostPath;
}
}
}

90
Runtime/painting/text_painter.cs


using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.painting {
class _CaretMetrics {
public _CaretMetrics(Offset offset, float? fullHeight) {
this.offset = offset;
this.fullHeight = fullHeight;
}
public Offset offset;
public float? fullHeight;
}
public class TextPainter {
TextSpan _text;
TextAlign _textAlign;

TextDirection textDirection = TextDirection.ltr,
float textScaleFactor = 1.0f,
int? maxLines = null,
string ellipsis = "") {
string ellipsis = "",
StrutStyle strutStyle = null) {
this._text = text;
this._textAlign = textAlign;
this._textDirection = textDirection;

this._strutStyle = strutStyle;
}

}
}
public StrutStyle strutStyle {
get { return this._strutStyle; }
set {
if (this._strutStyle == value) {
return;
}
this._strutStyle = value;
this._paragraph = null;
this._needsLayout = true;
}
}
StrutStyle _strutStyle;
public float minIntrinsicWidth {
get {
Debug.Assert(!this._needsLayout);

}
public Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
this._computeCaretMetrics(position, caretPrototype);
return this._caretMetrics.offset;
}
public float getFullHeightForCaret(TextPosition position, Rect caretPrototype) {
this._computeCaretMetrics(position, caretPrototype);
return this._caretMetrics.fullHeight ?? 0;
}
_CaretMetrics _caretMetrics;
TextPosition _previousCaretPosition;
Rect _previousCaretPrototype;
void _computeCaretMetrics(TextPosition position, Rect caretPrototype) {
var offset = position.offset;
if (offset > 0) {
var prevCodeUnit = this._text.codeUnitAt(offset);
if (prevCodeUnit == null) // out of upper bounds
{
var rectNextLine = this._paragraph.getNextLineStartRect();
if (rectNextLine != null) {
return new Offset(rectNextLine.start, rectNextLine.top);
}
}
if (position == this._previousCaretPosition && caretPrototype == this._previousCaretPrototype) {
return;
var offset = position.offset;
Rect rect;
return this._getOffsetFromUpstream(offset, caretPrototype) ??
this._getOffsetFromDownstream(offset, caretPrototype) ?? this._emptyOffset;
rect = this._getRectFromUpstream(offset, caretPrototype) ??
this._getRectFromDownStream(offset, caretPrototype);
break;
return this._getOffsetFromDownstream(offset, caretPrototype) ??
this._getOffsetFromUpstream(offset, caretPrototype) ?? this._emptyOffset;
rect = this._getRectFromDownStream(offset, caretPrototype) ??
this._getRectFromUpstream(offset, caretPrototype);
break;
default:
throw new UIWidgetsError("Unknown Position Affinity");
return null;
this._caretMetrics = new _CaretMetrics(
offset: rect != null ? new Offset(rect.left, rect.top) : this._emptyOffset,
fullHeight: rect != null ? (float?) (rect.bottom - rect.top) : null);
}
public Paragraph.LineRange getLineRange(int lineNumber) {

textAlign: this.textAlign,
textDirection: this.textDirection ?? defaultTextDirection,
maxLines: this.maxLines,
ellipsis: this.ellipsis
ellipsis: this.ellipsis,
strutStyle: this._strutStyle
);
}

const int _zwjUtf16 = 0x200d;
Offset _getOffsetFromUpstream(int offset, Rect caretPrototype) {
Rect _getRectFromUpstream(int offset, Rect caretPrototype) {
string flattenedText = this._text.toPlainText();
var prevCodeUnit = this._text.codeUnitAt(Mathf.Max(0, offset - 1));
if (prevCodeUnit == null) {

TextBox box = boxes[0];
const int NEWLINE_CODE_UNIT = 10;
if (prevCodeUnit == NEWLINE_CODE_UNIT) {
return new Offset(this._emptyOffset.dx, box.bottom);
return Rect.fromLTRB(this._emptyOffset.dx, box.bottom,
this._emptyOffset.dx, box.bottom + box.bottom - box.top);
return new Offset(dx, box.top);
return Rect.fromLTRB(Mathf.Min(dx, this.width), box.top,
Mathf.Min(dx, this.width), box.bottom);
Offset _getOffsetFromDownstream(int offset, Rect caretPrototype) {
Rect _getRectFromDownStream(int offset, Rect caretPrototype) {
string flattenedText = this._text.toPlainText();
var nextCodeUnit =
this._text.codeUnitAt(Mathf.Min(offset, flattenedText == null ? 0 : flattenedText.Length - 1));

TextBox box = boxes[boxes.Count - 1];
float caretStart = box.start;
float dx = box.direction == TextDirection.rtl ? caretStart - caretPrototype.width : caretStart;
return new Offset(dx, box.top);
return Rect.fromLTRB(Mathf.Min(dx, this.width), box.top,
Mathf.Min(dx, this.width), box.bottom);
}
return null;

192
Runtime/painting/text_style.cs


public static readonly float _defaultFontSize = 14.0f;
public readonly bool inherit;
public readonly Color color;
public readonly Color backgroundColor;
public readonly float? fontSize;
public readonly FontWeight fontWeight;
public readonly FontStyle? fontStyle;

public readonly TextDecoration decoration;
public readonly Color decorationColor;
public readonly TextDecorationStyle? decorationStyle;
public readonly float? decorationThickness;
public readonly Paint foreground;
public List<string> fontFamilyFallback {
get { return this._fontFamilyFallback; }
}
readonly List<string> _fontFamilyFallback;
const string _kColorForegroundWarning = "Cannot provide both a color and a foreground\n" +
"The color argument is just a shorthand for 'foreground: new Paint()..color = color'.";
public TextStyle(bool inherit = true, Color color = null, float? fontSize = null,
const string _kColorBackgroundWarning = "Cannot provide both a backgroundColor and a background\n" +
"The backgroundColor argument is just a shorthand for 'background: new Paint()..color = color'.";
public TextStyle(bool inherit = true,
Color color = null,
Color backgroundColor = null,
float? fontSize = null,
FontStyle? fontStyle = null, float? letterSpacing = null, float? wordSpacing = null,
TextBaseline? textBaseline = null, float? height = null, Paint background = null,
FontStyle? fontStyle = null,
float? letterSpacing = null,
float? wordSpacing = null,
TextBaseline? textBaseline = null,
float? height = null,
Paint foreground = null,
Paint background = null,
Color decorationColor = null, TextDecorationStyle? decorationStyle = null,
string fontFamily = null, string debugLabel = null) {
Color decorationColor = null,
TextDecorationStyle? decorationStyle = null,
float? decorationThickness = null,
string fontFamily = null,
List<string> fontFamilyFallback = null,
string debugLabel = null) {
D.assert(color == null || foreground == null, () => _kColorForegroundWarning);
D.assert(backgroundColor == null || background == null, () => _kColorBackgroundWarning);
this.backgroundColor = backgroundColor;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;

this.decoration = decoration;
this.decorationColor = decorationColor;
this.decorationStyle = decorationStyle;
this.decorationThickness = decorationThickness;
this._fontFamilyFallback = fontFamilyFallback;
this.debugLabel = debugLabel;
this.background = background;
}

public TextStyle apply(
Color color = null,
Color backgroundColor = null,
float decorationThicknessFactor = 1.0f,
float decorationThicknessDelta = 0.0f,
List<string> fontFamilyFallback = null,
float fontSizeFactor = 1.0f,
float fontSizeDelta = 0.0f,
int fontWeightDelta = 0,

float heightFactor = 1.0f,
float heightDelta = 0.0f
) {
D.assert(this.fontSize != null || (fontSizeFactor == 1.0 && fontSizeDelta == 0.0));
D.assert(this.fontWeight != null || fontWeightDelta == 0.0);
D.assert(this.letterSpacing != null || (letterSpacingFactor == 1.0 && letterSpacingDelta == 0.0));
D.assert(this.wordSpacing != null || (wordSpacingFactor == 1.0 && wordSpacingDelta == 0.0));
D.assert(this.height != null || (heightFactor == 1.0 && heightDelta == 0.0));
D.assert(this.fontSize != null || (fontSizeFactor == 1.0f && fontSizeDelta == 0.0f));
D.assert(this.fontWeight != null || fontWeightDelta == 0.0f);
D.assert(this.letterSpacing != null || (letterSpacingFactor == 1.0f && letterSpacingDelta == 0.0f));
D.assert(this.wordSpacing != null || (wordSpacingFactor == 1.0f && wordSpacingDelta == 0.0f));
D.assert(this.height != null || (heightFactor == 1.0f && heightDelta == 0.0f));
D.assert(this.decorationThickness != null ||
(decorationThicknessFactor == 1.0f && decorationThicknessDelta == 0.0f));
string modifiedDebugLabel = "";
D.assert(() => {

return new TextStyle(
inherit: this.inherit,
color: color ?? this.color,
color: this.foreground == null ? color ?? this.color : null,
backgroundColor: this.background == null ? backgroundColor ?? this.backgroundColor : null,
fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback,
fontSize: this.fontSize == null ? null : this.fontSize * fontSizeFactor + fontSizeDelta,
fontWeight: this.fontWeight == null ? null : this.fontWeight,
fontStyle: this.fontStyle,

wordSpacing: this.wordSpacing == null ? null : this.wordSpacing * wordSpacingFactor + wordSpacingDelta,
textBaseline: this.textBaseline,
height: this.height == null ? null : this.height * heightFactor + heightDelta,
foreground: this.foreground,
decorationThickness: this.decorationThickness == null
? null
: this.decorationThickness * decorationThicknessFactor + decorationThicknessDelta,
debugLabel: modifiedDebugLabel
);
}

return this.copyWith(
color: other.color,
backgroundColor: other.backgroundColor,
fontFamilyFallback: other.fontFamilyFallback,
fontSize: other.fontSize,
fontWeight: other.fontWeight,
fontStyle: other.fontStyle,

height: other.height,
foreground: other.foreground,
background: other.background,
background: other.background,
decorationThickness: other.decorationThickness,
public TextStyle copyWith(Color color = null,
public TextStyle copyWith(
bool? inherit = null,
Color color = null,
Color backgroundColor = null,
List<string> fontFamilyFallback = null,
float? fontSize = null,
FontWeight fontWeight = null,
FontStyle? fontStyle = null,

float? height = null,
Paint foreground = null,
float? decorationThickness = null,
D.assert(color == null || foreground == null, () => _kColorForegroundWarning);
D.assert(backgroundColor == null || background == null, () => _kColorBackgroundWarning);
string newDebugLabel = null;
D.assert(() => {
if (this.debugLabel != null) {

});
return new TextStyle(
inherit: this.inherit,
color: color ?? this.color,
inherit: inherit ?? this.inherit,
color: this.foreground == null && foreground == null ? color ?? this.color : null,
backgroundColor: this.background == null && background == null ? color ?? this.color : null,
fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback,
fontSize: fontSize ?? this.fontSize,
fontWeight: fontWeight ?? this.fontWeight,
fontStyle: fontStyle ?? this.fontStyle,

decoration: decoration ?? this.decoration,
decorationColor: decorationColor ?? this.decorationColor,
decorationStyle: decorationStyle ?? this.decorationStyle,
decorationThickness: decorationThickness ?? this.decorationThickness,
background: background ?? this.background,
debugLabel: newDebugLabel
);

return new TextStyle(
inherit: b.inherit,
color: Color.lerp(null, b.color, t),
fontFamily: t < 0.5 ? null : b.fontFamily,
fontSize: t < 0.5 ? null : b.fontSize,
fontWeight: t < 0.5 ? null : b.fontWeight,
fontStyle: t < 0.5 ? null : b.fontStyle,
letterSpacing: t < 0.5 ? null : b.letterSpacing,
wordSpacing: t < 0.5 ? null : b.wordSpacing,
textBaseline: t < 0.5 ? null : b.textBaseline,
height: t < 0.5 ? null : b.height,
background: t < 0.5 ? null : b.background,
decoration: t < 0.5 ? null : b.decoration,
backgroundColor: Color.lerp(null, b.backgroundColor, t),
fontFamily: t < 0.5f ? null : b.fontFamily,
fontFamilyFallback: t < 0.5f ? null : b.fontFamilyFallback,
fontSize: t < 0.5f ? null : b.fontSize,
fontWeight: t < 0.5f ? null : b.fontWeight,
fontStyle: t < 0.5f ? null : b.fontStyle,
letterSpacing: t < 0.5f ? null : b.letterSpacing,
wordSpacing: t < 0.5f ? null : b.wordSpacing,
textBaseline: t < 0.5f ? null : b.textBaseline,
height: t < 0.5f ? null : b.height,
foreground: t < 0.5f ? null : b.foreground,
background: t < 0.5f ? null : b.background,
decoration: t < 0.5f ? null : b.decoration,
decorationStyle: t < 0.5 ? null : b.decorationStyle,
decorationStyle: t < 0.5f ? null : b.decorationStyle,
decorationThickness: t < 0.5f ? null : b.decorationThickness,
debugLabel: lerpDebugLabel
);
}

inherit: a.inherit,
color: Color.lerp(a.color, null, t),
fontFamily: t < 0.5 ? a.fontFamily : null,
fontSize: t < 0.5 ? a.fontSize : null,
fontWeight: t < 0.5 ? a.fontWeight : null,
fontStyle: t < 0.5 ? a.fontStyle : null,
letterSpacing: t < 0.5 ? a.letterSpacing : null,
wordSpacing: t < 0.5 ? a.wordSpacing : null,
textBaseline: t < 0.5 ? a.textBaseline : null,
height: t < 0.5 ? a.height : null,
background: t < 0.5 ? a.background : null,
decoration: t < 0.5 ? a.decoration : null,
backgroundColor: Color.lerp(a.backgroundColor, null, t),
fontFamily: t < 0.5f ? a.fontFamily : null,
fontFamilyFallback: t < 0.5f ? a.fontFamilyFallback : null,
fontSize: t < 0.5f ? a.fontSize : null,
fontWeight: t < 0.5f ? a.fontWeight : null,
fontStyle: t < 0.5f ? a.fontStyle : null,
letterSpacing: t < 0.5f ? a.letterSpacing : null,
wordSpacing: t < 0.5f ? a.wordSpacing : null,
textBaseline: t < 0.5f ? a.textBaseline : null,
height: t < 0.5f ? a.height : null,
foreground: t < 0.5f ? a.foreground : null,
background: t < 0.5f ? a.background : null,
decoration: t < 0.5f ? a.decoration : null,
decorationStyle: t < 0.5 ? a.decorationStyle : null,
decorationStyle: t < 0.5f ? a.decorationStyle : null,
decorationThickness: t < 0.5f ? a.decorationThickness : null,
debugLabel: lerpDebugLabel
);
}

color: Color.lerp(a.color, b.color, t),
color: a.foreground == null && b.foreground == null ? Color.lerp(a.color, b.color, t) : null,
backgroundColor: a.background == null && b.background == null
? Color.lerp(a.backgroundColor, b.backgroundColor, t)
: null,
fontFamilyFallback: t < 0.5 ? a.fontFamilyFallback : b.fontFamilyFallback,
fontSize: MathUtils.lerpNullableFloat(a.fontSize ?? b.fontSize, b.fontSize ?? a.fontSize, t),
fontWeight: t < 0.5 ? a.fontWeight : b.fontWeight,
fontStyle: t < 0.5 ? a.fontStyle : b.fontStyle,

b.wordSpacing ?? a.wordSpacing, t),
textBaseline: t < 0.5 ? a.textBaseline : b.textBaseline,
height: MathUtils.lerpNullableFloat(a.height ?? b.height, b.height ?? a.height, t),
background: t < 0.5 ? a.background : b.background,
foreground: (a.foreground != null || b.foreground != null)
? t < 0.5
? a.foreground ?? new Paint() {color = a.color}
: b.foreground ?? new Paint() {color = b.color}
: null,
background: (a.background != null || b.background != null)
? t < 0.5
? a.background ?? new Paint() {color = a.backgroundColor}
: b.background ?? new Paint() {color = b.backgroundColor}
: null,
decorationThickness: MathUtils.lerpFloat(
a.decorationThickness ?? b.decorationThickness ?? 0.0f,
b.decorationThickness ?? a.decorationThickness ?? 0.0f, t),
debugLabel: lerpDebugLabel
);
}

List<DiagnosticsNode> styles = new List<DiagnosticsNode>();
styles.Add(new DiagnosticsProperty<Color>("color", this.color,
defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new DiagnosticsProperty<Color>("backgroundColor", this.backgroundColor,
styles.Add(new EnumerableProperty<string>("familyFallback", this.fontFamilyFallback,
defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new DiagnosticsProperty<float?>("size", this.fontSize,
defaultValue: Diagnostics.kNullDefaultValue));
string weightDescription = "";

defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new DiagnosticsProperty<float?>("height", this.height,
defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new StringProperty("foreground", this.foreground == null ? null : this.foreground.ToString(),
defaultValue: Diagnostics.kNullDefaultValue, quoted: false));
styles.Add(new StringProperty("background", this.background == null ? null : this.background.ToString(),
defaultValue: Diagnostics.kNullDefaultValue, quoted: false));
if (this.decoration != null) {

D.assert(decorationDescription.isNotEmpty);
styles.Add(new MessageProperty("decoration", string.Join(" ", decorationDescription.ToArray())));
styles.Add(new FloatProperty("decorationThickness", this.decorationThickness, unit: "x",
defaultValue: Diagnostics.kNoDefaultValue));
}
bool styleSpecified = styles.Any((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info));

return true;
}
return this.inherit == other.inherit && Equals(this.color, other.color) &&
this.fontSize.Equals(other.fontSize) && this.fontWeight == other.fontWeight &&
this.fontStyle == other.fontStyle && this.letterSpacing.Equals(other.letterSpacing) &&
this.wordSpacing.Equals(other.wordSpacing) && this.textBaseline == other.textBaseline &&
return this.inherit == other.inherit &&
Equals(this.color, other.color) &&
Equals(this.backgroundColor, other.backgroundColor) &&
this.fontSize.Equals(other.fontSize) &&
this.fontWeight == other.fontWeight &&
this.fontStyle == other.fontStyle &&
this.letterSpacing.Equals(other.letterSpacing) &&
this.wordSpacing.Equals(other.wordSpacing) &&
this.textBaseline == other.textBaseline &&
this.decorationStyle == other.decorationStyle && Equals(this.background, other.background) &&
this.decorationStyle == other.decorationStyle &&
this.decorationThickness == other.decorationThickness &&
Equals(this.foreground, other.foreground) &&
Equals(this.background, other.background) &&
CollectionUtils.equalsList(this.fontFamilyFallback, other.fontFamilyFallback) &&
string.Equals(this.fontFamily, other.fontFamily);
}

unchecked {
var hashCode = this.inherit.GetHashCode();
hashCode = (hashCode * 397) ^ (this.color != null ? this.color.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.backgroundColor != null ? this.backgroundColor.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ (this.fontWeight != null ? this.fontWeight.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.fontStyle.GetHashCode();

hashCode = (hashCode * 397) ^ (this.decoration != null ? this.decoration.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.decorationColor != null ? this.decorationColor.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.decorationStyle.GetHashCode();
hashCode = (hashCode * 397) ^ this.decorationThickness.GetHashCode();
hashCode = (hashCode * 397) ^ (this.foreground != null ? this.foreground.GetHashCode() : 0);
hashCode = (hashCode * 397) ^
(this.fontFamilyFallback != null ? this.fontFamilyFallback.GetHashCode() : 0);
return hashCode;
}
}

1
Runtime/rendering/binding.cs


Window.instance.onMetricsChanged += this.handleMetricsChanged;
Window.instance.onTextScaleFactorChanged += this.handleTextScaleFactorChanged;
Window.instance.onPlatformBrightnessChanged += this.handlePlatformBrightnessChanged;
this.initRenderView();
D.assert(this.renderView != null);
this.addPersistentFrameCallback(this._handlePersistentFrameCallback);

4
Runtime/rendering/box.cs


if (this.constraints.hasBoundedWidth) {
testIntrinsicsForValues(this.getMinIntrinsicWidth, this.getMaxIntrinsicWidth, "Width",
this.constraints.maxWidth);
this.constraints.maxHeight);
this.constraints.maxHeight);
this.constraints.maxWidth);
}
debugCheckingIntrinsics = false;

129
Runtime/rendering/editable.cs


using System.Collections.Generic;
using System.Xml.Schema;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;

TextPainter _textPainter;
Color _cursorColor;
int? _maxLines;
int? _minLines;
bool _expands;
Color _selectionColor;
ViewportOffset _offset;
ValueNotifier<bool> _showCursor;

Color backgroundCursorColor = null,
bool? hasFocus = null,
int? maxLines = 1,
int? minLines = null,
bool expands = false,
StrutStyle strutStyle = null,
Color selectionColor = null,
TextSelection selection = null,
bool obscureText = false,

float cursorWidth = 1.0f,
Radius cursorRadius = null,
bool? enableInteractiveSelection = null,
bool? enableInteractiveSelection = null,
D.assert(minLines == null || minLines > 0);
D.assert((minLines == null) || maxLines >= minLines, () => "minLines can't be greater than maxLines");
textScaleFactor: textScaleFactor);
textScaleFactor: textScaleFactor, strutStyle: strutStyle);
this._minLines = minLines;
this._expands = expands;
this._selectionColor = selectionColor;
this._selection = selection;
this._obscureText = obscureText;

public TextSelectionDelegate textSelectionDelegate;
public ValueListenable<bool> selectionStartInViewport {
get { return this._selectionStartInViewport; }
}
readonly ValueNotifier<bool> _selectionStartInViewport = new ValueNotifier<bool>(true);
public ValueListenable<bool> selectionEndInViewport {
get { return this._selectionEndInViewport; }
}
readonly ValueNotifier<bool> _selectionEndInViewport = new ValueNotifier<bool>(true);
void _updateSelectionExtentsVisibility(Offset effectiveOffset) {
Rect visibleRegion = Offset.zero & this.size;
Offset startOffset = this._textPainter.getOffsetForCaret(
new TextPosition(offset: this._selection.start, affinity: this._selection.affinity),
Rect.zero
);
float visibleRegionSlop = 0.5f;
this._selectionStartInViewport.value = visibleRegion
.inflate(visibleRegionSlop)
.contains(startOffset + effectiveOffset);
Offset endOffset = this._textPainter.getOffsetForCaret(
new TextPosition(offset: this._selection.end, affinity: this._selection.affinity),
Rect.zero
);
this._selectionEndInViewport.value = visibleRegion
.inflate(visibleRegionSlop)
.contains(endOffset + effectiveOffset);
}
int _extentOffset = -1;
int _baseOffset = -1;

}
}
public StrutStyle strutStyle {
get { return this._textPainter.strutStyle; }
set {
if (this._textPainter.strutStyle == value) {
return;
}
this._textPainter.strutStyle = value;
this.markNeedsTextLayout();
}
}
public Color cursorColor {
get { return this._cursorColor; }
set {

}
}
bool _hasFocus;
bool _hasFocus = false;
bool _listenerAttached = false;
public bool hasFocus {

}
}
public int? minLines {
get { return this._minLines; }
set {
D.assert(value == null || value > 0);
if (this._minLines == value) {
return;
}
this._minLines = value;
this.markNeedsTextLayout();
}
}
public bool expands {
get { return this._expands; }
set {
if (this.expands == value) {
return;
}
this._expands = value;
this.markNeedsTextLayout();
}
}
public Color selectionColor {
get { return this._selectionColor; }
set {

}
public void handleTapDown(TapDownDetails details) {
this._lastTapDownPosition = details.globalPosition - this._paintOffset;
this._lastTapDownPosition = details.globalPosition;
if (!Application.isMobilePlatform) {
this.selectPosition(SelectionChangedCause.tap);
}

this.selectWordsInRange(from: this._lastTapDownPosition, cause: cause);
}
void selectWordsInRange(Offset from = null, Offset to = null, SelectionChangedCause? cause = null) {
public void selectWordsInRange(Offset from = null, Offset to = null, SelectionChangedCause? cause = null) {
D.assert(cause != null);
D.assert(from != null);
this._layoutText(this.constraints.maxWidth);

D.assert(this._lastTapDownPosition != null);
if (this.onSelectionChanged != null) {
TextPosition position =
this._textPainter.getPositionForOffset(this.globalToLocal(this._lastTapDownPosition));
this._textPainter.getPositionForOffset(this.globalToLocal(this._lastTapDownPosition - this._paintOffset));
TextRange word = this._textPainter.getWordBoundary(position);
if (position.offset - word.start <= 1) {
this.onSelectionChanged(

void _paintCaret(Canvas canvas, Offset effectiveOffset, TextPosition textPosition) {
D.assert(this._textLayoutLastWidth == this.constraints.maxWidth);
var caretOffset = this._textPainter.getOffsetForCaret(textPosition, this._caretPrototype);
Rect caretRect = this._caretPrototype.shift(caretOffset + effectiveOffset);
var caretOffset = this._textPainter.getOffsetForCaret(textPosition, this._caretPrototype) + effectiveOffset;
Rect caretRect = this._caretPrototype.shift(caretOffset);
#if !UNITY_IOS
if (this._textPainter.getFullHeightForCaret(textPosition, this._caretPrototype) != null) {
caretRect = Rect.fromLTWH(
caretRect.left,
caretRect.top - _kCaretHeightOffset,
caretRect.width,
this._textPainter.getFullHeightForCaret(textPosition, this._caretPrototype)
);
}
#endif
caretRect = caretRect.shift(this._getPixelPerfectCursorOffset(caretRect));
if (this.cursorRadius == null) {
canvas.drawRect(caretRect, paint);

}
float _preferredHeight(float width) {
if (this.maxLines != null) {
bool lockedMax = this.maxLines != null && this.minLines == null;
bool lockedBoth = this.maxLines != null && this.minLines == this.maxLines;
bool singleLine = this.maxLines == 1;
if (singleLine || lockedMax || lockedBoth) {
}
bool minLimited = this.minLines != null && this.minLines > 1;
bool maxLimited = this.maxLines != null;
if (minLimited || maxLimited) {
this._layoutText(width);
if (minLimited && this._textPainter.height < this.preferredLineHeight * this.minLines.Value) {
return this.preferredLineHeight * this.minLines.Value;
}
if (maxLimited && this._textPainter.height > this.preferredLineHeight * this.maxLines.Value) {
return this.preferredLineHeight * this.maxLines.Value;
}
}
if (!width.isFinite()) {

properties.add(new DiagnosticsProperty<Color>("cursorColor", this.cursorColor));
properties.add(new DiagnosticsProperty<ValueNotifier<bool>>("showCursor", this.showCursor));
properties.add(new DiagnosticsProperty<int?>("maxLines", this.maxLines));
properties.add(new DiagnosticsProperty<int?>("minLines", this.minLines));
properties.add(new DiagnosticsProperty<bool>("expands", this.expands));
properties.add(new DiagnosticsProperty<Color>("selectionColor", this.selectionColor));
properties.add(new DiagnosticsProperty<float>("textScaleFactor", this.textScaleFactor));
properties.add(new DiagnosticsProperty<TextSelection>("selection", this.selection));

2
Runtime/rendering/error.cs


);
static ParagraphStyle paragraphStyle = new ParagraphStyle(
lineHeight: 1.0f
height: 1.0f
);
}
}

5
Runtime/rendering/flex.cs


if (totalFlex > 0 || this.crossAxisAlignment == CrossAxisAlignment.baseline) {
float spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : float.NaN;
child = this.firstChild;
float maxSizeAboveBaseline = 0;
float maxSizeBelowBaseline = 0;
while (child != null) {
int flex = this._getFlex(child);
if (flex > 0) {

float? distance = child.getDistanceToBaseline(this.textBaseline, onlyReal: true);
if (distance != null) {
maxBaselineDistance = Mathf.Max(maxBaselineDistance, distance.Value);
maxSizeAboveBaseline = Mathf.Max(distance.Value, maxSizeAboveBaseline);
maxSizeBelowBaseline = Mathf.Max(child.size.height - distance.Value, maxSizeBelowBaseline);
crossSize = maxSizeAboveBaseline + maxSizeBelowBaseline;
}
}

164
Runtime/rendering/layer.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.external.simplejson;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;

public Layer lastChild {
get { return this._lastChild; }
}
internal override S find<S>(Offset regionOffset) {
Layer current = this.lastChild;
while (current != null) {

return child == equals;
}
PictureLayer _highlightConflictingLayer(PhysicalModelLayer child) {
PictureRecorder recorder = new PictureRecorder();
var canvas = new RecorderCanvas(recorder);
canvas.drawPath(child.clipPath, new Paint() {
color = new Color(0xFFAA0000),
style = PaintingStyle.stroke,
strokeWidth = child.elevation + 10.0f,
});
PictureLayer pictureLayer = new PictureLayer(child.clipPath.getBounds());
pictureLayer.picture = recorder.endRecording();
pictureLayer.debugCreator = child;
child.append(pictureLayer);
return pictureLayer;
}
List<PictureLayer> _processConflictingPhysicalLayers(PhysicalModelLayer predecessor, PhysicalModelLayer child) {
UIWidgetsError.reportError(new UIWidgetsErrorDetails(
exception: new UIWidgetsError("Painting order is out of order with respect to elevation.\n" +
"See https://api.flutter.dev/flutter/rendering/debugCheckElevations.html " +
"for more details."),
context: "during compositing",
informationCollector: (StringBuilder builder) => {
builder.AppendLine("Attempted to composite layer");
builder.AppendLine(child.ToString());
builder.AppendLine("after layer");
builder.AppendLine(predecessor.ToString());
builder.AppendLine("which occupies the same area at a higher elevation.");
}
));
return new List<PictureLayer> {
this._highlightConflictingLayer(predecessor),
this._highlightConflictingLayer(child)
};
}
protected List<PictureLayer> _debugCheckElevations() {
List<PhysicalModelLayer> physicalModelLayers =
this.depthFirstIterateChildren().OfType<PhysicalModelLayer>().ToList();
List<PictureLayer> addedLayers = new List<PictureLayer>();
for (int i = 0; i < physicalModelLayers.Count; i++) {
PhysicalModelLayer physicalModelLayer = physicalModelLayers[i];
D.assert(physicalModelLayer.lastChild?.debugCreator != physicalModelLayer,
() => "debugCheckElevations has either already visited this layer or failed to remove the" +
" added picture from it.");
float accumulatedElevation = physicalModelLayer.elevation;
Layer ancestor = physicalModelLayer.parent;
while (ancestor != null) {
if (ancestor is PhysicalModelLayer modelLayer) {
accumulatedElevation += modelLayer.elevation;
}
ancestor = ancestor.parent;
}
for (int j = 0; j <= i; j++) {
PhysicalModelLayer predecessor = physicalModelLayers[j];
float predecessorAccumulatedElevation = predecessor.elevation;
ancestor = predecessor.parent;
while (ancestor != null) {
if (ancestor == predecessor) {
continue;
}
if (ancestor is PhysicalModelLayer modelLayer) {
predecessorAccumulatedElevation += modelLayer.elevation;
}
ancestor = ancestor.parent;
}
if (predecessorAccumulatedElevation <= accumulatedElevation) {
continue;
}
Path intersection = Path.combine(
PathOperation.intersect,
predecessor._debugTransformedClipPath,
physicalModelLayer._debugTransformedClipPath);
if (intersection != null && intersection.computeMetrics().Any((metric) => metric.length > 0)) {
addedLayers.AddRange(this._processConflictingPhysicalLayers(predecessor, physicalModelLayer));
}
}
}
return addedLayers;
}
internal override void updateSubtreeNeedsAddToScene() {
base.updateSubtreeNeedsAddToScene();
Layer child = this.firstChild;

D.assert(transform != null);
}
public List<Layer> depthFirstIterateChildren() {
if (this.firstChild == null) {
return new List<Layer>();
}
List<Layer> children = new List<Layer>();
Layer child = this.firstChild;
while (child != null) {
children.Add(child);
if (child is ContainerLayer containerLayer) {
children.AddRange(containerLayer.depthFirstIterateChildren());
}
child = child.nextSibling;
}
return children;
}
public override List<DiagnosticsNode> debugDescribeChildren() {
var children = new List<DiagnosticsNode>();
if (this.firstChild == null) {

}
public Scene buildScene(SceneBuilder builder) {
List<PictureLayer> temporaryLayers = null;
D.assert(() => {
if (RenderingDebugUtils.debugCheckElevationsEnabled) {
temporaryLayers = this._debugCheckElevations();
}
return true;
});
return builder.build();
Scene scene = builder.build();
D.assert(() => {
if (temporaryLayers != null) {
foreach (PictureLayer temporaryLayer in temporaryLayers) {
temporaryLayer.remove();
}
}
return true;
});
return scene;
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {

if (this._invertedTransform == null) {
return null;
}
Offset transform = this._invertedTransform.mapXY(regionOffset.dx, regionOffset.dy);
return base.find<S>(transform);
}

public override void applyTransform(Layer child, Matrix3 transform) {
D.assert(child != null);
D.assert(transform != null);
transform.preConcat(this._lastEffectiveTransform);
D.assert(this._lastEffectiveTransform != null || this.transform != null);
if (this._lastEffectiveTransform == null) {
transform.preConcat(this.transform);
}
else {
transform.preConcat(this._lastEffectiveTransform);
}
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

properties.add(new DiagnosticsProperty<Offset>("offset", this.offset));
}
}
public class BackdropFilterLayer : ContainerLayer {
public BackdropFilterLayer(ImageFilter filter = null) {
D.assert(filter != null);

protected override bool alwaysNeedsAddToScene {
get { return true; }
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;

}
}
}
internal Path _debugTransformedClipPath {
get {
ContainerLayer ancestor = this.parent;
Matrix3 matrix = Matrix3.I();
while (ancestor != null && ancestor.parent != null) {
ancestor.applyTransform(this, matrix);
ancestor = ancestor.parent;
}
return this.clipPath.transform(matrix);
}
}
Clip _clipBehavior;

9
Runtime/rendering/object.cs


using Unity.UIWidgets.ui;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.rendering {

Paint paint = new Paint {
style = PaintingStyle.stroke,
strokeWidth = 1.0f,
color = new ui.Color(0xFFFF9800),
color = new Color(0xFFFF9800),
};
this.canvas.drawRect(this.estimatedBounds, paint);
}

Matrix3 effectiveTransform;
if (offset == null || offset == Offset.zero) {
effectiveTransform = transform;
} else {
}
else {
effectiveTransform = Matrix3.makeTrans(offset.dx, offset.dy);
effectiveTransform.preConcat(transform);
effectiveTransform.preTranslate(-offset.dx, -offset.dy);

var inverse = Matrix3.I();
var invertible = effectiveTransform.invert(inverse);
// it could just be "scale == 0", ignore the assertion.
// D.assert(invertible);

}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<object>(
"creator", this.debugCreator, defaultValue: Diagnostics.kNullDefaultValue,
level: DiagnosticLevel.debug));

45
Runtime/rendering/paragraph.cs


/// Use an ellipsis to indicate that the text has overflowed.
ellipsis,
/// Render overflowing text outside of its container.
visible,
}

TextOverflow _overflow;
readonly TextPainter _textPainter;
bool _hasVisualOverflow = false;
bool _needsClipping = false;
List<TextBox> _selectionRects;

TextOverflow overflow = TextOverflow.clip,
float textScaleFactor = 1.0f,
int? maxLines = null,
StrutStyle strutStyle = null,
Action onSelectionChanged = null,
Color selectionColor = null
) {

textDirection,
textScaleFactor,
maxLines,
overflow == TextOverflow.ellipsis ? _kEllipsis : ""
overflow == TextOverflow.ellipsis ? _kEllipsis : "",
strutStyle: strutStyle
);
this._selection = null;

protected override void performLayout() {
this._layoutTextWithConstraints(this.constraints);
var textSize = this._textPainter.size;
var didOverflowHeight = this._textPainter.didExceedMaxLines;
var textDidExceedMaxLines = this._textPainter.didExceedMaxLines;
var didOverflowHeight = this.size.height < textSize.height || textDidExceedMaxLines;
this._hasVisualOverflow = didOverflowWidth || didOverflowHeight;
var hasVisualOverflow = didOverflowWidth || didOverflowHeight;
if (hasVisualOverflow) {
switch (this._overflow) {
case TextOverflow.visible:
this._needsClipping = false;
break;
case TextOverflow.clip:
case TextOverflow.ellipsis:
case TextOverflow.fade:
this._needsClipping = true;
break;
}
}
else {
this._needsClipping = false;
}
this._selectionRects = null;
}

this._layoutTextWithConstraints(this.constraints);
var canvas = context.canvas;
if (this._hasVisualOverflow) {
if (this._needsClipping) {
var bounds = offset & this.size;
canvas.save();
canvas.clipRect(bounds);

}
this._textPainter.paint(canvas, offset);
if (this._hasVisualOverflow) {
if (this._needsClipping) {
canvas.restore();
}
}

}
canvas.drawPath(barPath, paint);
}
public StrutStyle strutStyle {
get { return this._textPainter.strutStyle; }
set {
if (this._textPainter.strutStyle == value) {
return;
}
this._textPainter.strutStyle = value;
this.markNeedsLayout();
}
}
void _layoutText(float minWidth = 0.0f, float maxWidth = float.PositiveInfinity) {

104
Runtime/rendering/proxy_box.cs


Color _color;
protected static Paint _transparentPaint {
get { return new Paint {color = new Color(0x00000000)}; }
}
get { return this._elevation != 0.0; }
get { return true; }
}
public override void debugFillProperties(DiagnosticPropertiesBuilder description) {

Path offsetRRectAsPath = new Path();
offsetRRectAsPath.addRRect(offsetRRect);
if (this.needsCompositing) {
PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetRRectAsPath,
clipBehavior: this.clipBehavior,
elevation: this.elevation,
color: this.color,
shadowColor: this.shadowColor);
context.pushLayer(physicalModel, base.paint, offset, childPaintBounds: offsetBounds);
}
else {
Canvas canvas = context.canvas;
if (this.elevation != 0.0) {
canvas.drawRect(
offsetBounds.inflate(20.0f),
_transparentPaint
);
canvas.drawShadow(
offsetRRectAsPath,
this.shadowColor,
this.elevation,
this.color.alpha != 0xFF
);
}
Paint paint = new Paint {color = this.color};
canvas.drawRRect(offsetRRect, paint);
context.clipRRectAndPaint(offsetRRect, this.clipBehavior, offsetBounds,
() => base.paint(context, offset));
D.assert(context.canvas == canvas, () => "canvas changed even though needsCompositing was false");
}
PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetRRectAsPath,
clipBehavior: this.clipBehavior,
elevation: this.elevation,
color: this.color,
shadowColor: this.shadowColor);
D.assert(() => {
physicalModel.debugCreator = this.debugCreator;
return true;
});
context.pushLayer(physicalModel, base.paint, offset, childPaintBounds: offsetBounds);
}
}

Path offsetPath = new Path();
offsetPath.addPath(this._clip, offset);
if (this.needsCompositing) {
PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetPath,
clipBehavior: this.clipBehavior,
elevation: this.elevation,
color: this.color,
shadowColor: this.shadowColor);
context.pushLayer(physicalModel, base.paint, offset, childPaintBounds: offsetBounds);
}
else {
Canvas canvas = context.canvas;
if (this.elevation != 0.0) {
canvas.drawRect(
offsetBounds.inflate(20.0f),
_transparentPaint
);
canvas.drawShadow(
offsetPath,
this.shadowColor,
this.elevation,
this.color.alpha != 0xFF
);
}
Paint paint = new Paint {color = this.color, style = PaintingStyle.fill};
canvas.drawPath(offsetPath, paint);
context.clipPathAndPaint(offsetPath, this.clipBehavior,
offsetBounds, () => base.paint(context, offset));
D.assert(context.canvas == canvas, () => "canvas changed even though needsCompositing was false");
}
PhysicalModelLayer physicalModel = new PhysicalModelLayer(
clipPath: offsetPath,
clipBehavior: this.clipBehavior,
elevation: this.elevation,
color: this.color,
shadowColor: this.shadowColor);
context.pushLayer(physicalModel, base.paint, offset, childPaintBounds: offsetBounds);
}
}

public delegate void PointerCancelEventListener(PointerCancelEvent evt);
public delegate void PointerSignalEventListener(PointerSignalEvent evt);
public delegate void PointerScrollEventListener(PointerScrollEvent evt);
public class RenderPointerListener : RenderProxyBoxWithHitTestBehavior {

PointerExitEventListener onPointerExit = null,
PointerUpEventListener onPointerUp = null,
PointerCancelEventListener onPointerCancel = null,
PointerSignalEventListener onPointerSignal = null,
PointerScrollEventListener onPointerScroll = null,
PointerDragFromEditorEnterEventListener onPointerDragFromEditorEnter = null,
PointerDragFromEditorHoverEventListener onPointerDragFromEditorHover = null,

this.onPointerMove = onPointerMove;
this.onPointerUp = onPointerUp;
this.onPointerCancel = onPointerCancel;
this.onPointerSignal = onPointerSignal;
this.onPointerScroll = onPointerScroll;
this._onPointerEnter = onPointerEnter;

public PointerCancelEventListener onPointerCancel;
public PointerSignalEventListener onPointerSignal;
public MouseTrackerAnnotation hoverAnnotation {
get { return this._hoverAnnotation; }
}
void _updateAnnotations() {
D.assert(this._onPointerEnter != this._hoverAnnotation.onEnter ||

return;
}
if (this.onPointerSignal != null && evt is PointerSignalEvent) {
this.onPointerSignal((PointerSignalEvent) evt);
return;
}
if (this.onPointerScroll != null && evt is PointerScrollEvent) {
this.onPointerScroll((PointerScrollEvent) evt);
}

if (this.onPointerCancel != null) {
listeners.Add("cancel");
}
if (this.onPointerSignal != null) {
listeners.Add("signal");
}
if (listeners.isEmpty()) {

3
Runtime/rendering/sliver.cs


public readonly bool hasVisualOverflow;
public readonly float? scrollOffsetCorrection;
public readonly float cacheExtent;
public const float precisionErrorTolerance = 1e-10f;
internal static string _debugCompareFloats(string labelA, float valueA, string labelB, float valueB) {
if (valueA.ToString("F1") != valueB.ToString("F1")) {

);
}
if (this.maxPaintExtent < this.paintExtent) {
if (this.paintExtent - this.maxPaintExtent > precisionErrorTolerance) {
verify(false,
"The \"maxPaintExtent\" is less than the \"paintExtent\".\n" +
_debugCompareFloats("maxPaintExtent", this.maxPaintExtent, "paintExtent",

3
Runtime/rendering/sliver_grid.cs


float _getOffsetFromStartInCrossAxis(float crossAxisStart) {
if (this.reverseCrossAxis == true) {
return (this.crossAxisCount * this.crossAxisStride - crossAxisStart - this.childCrossAxisExtent) ??
return (this.crossAxisCount * this.crossAxisStride - crossAxisStart - this.childCrossAxisExtent
- (this.crossAxisStride - this.childCrossAxisExtent)) ??
0.0f;
}

2
Runtime/rendering/sliver_list.cs


}
else {
float firstChildScrollOffset = earliestScrollOffset - this.paintExtentOf(this.firstChild);
if (firstChildScrollOffset < 0.0) {
if (firstChildScrollOffset < -SliverGeometry.precisionErrorTolerance) {
float correction = 0.0f;
while (earliestUsefulChild != null) {
D.assert(this.firstChild == earliestUsefulChild);

240
Runtime/ui/painting/path.cs


using System;
using System.Collections;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
public enum PathOperation {
difference,
intersect,
union,
xor,
reverseDifference,
}
public class Path {
const float _KAPPA90 = 0.5522847493f;

float _minX, _minY;
float _maxX, _maxY;
PathCache _cache;
static uint pathGlobalKey = 0;

public uint pathKey {
get {
return this._pathKey;
}
get { return this._pathKey; }
}
public Path(int capacity = 128) {

public List<float> commands => this._commands;
public List<float> commands {
get { return this._commands; }
}
public override string ToString() {
var sb = new StringBuilder("Path: count = " + this._commands.Count);

internal PathCache flatten(float scale) {
scale = Mathf.Round(scale * 2.0f) / 2.0f; // round to 0.5f
this._cache = new PathCache(scale);
var i = 0;

if (x < this._minX) {
this._minX = x;
}
if (y < this._minY) {
this._minY = y;
}

}
if (y > this._maxY) {
this._maxY = y;
}

return Rect.fromLTRB(this._minX, this._minY, this._maxX, this._maxY);
}
public static Path combine(PathOperation operation, Path path1, Path path2) {
D.assert(path1 != null);
D.assert(path2 != null);
Path path = null;
D.assert(() => {
Debug.LogWarning("Path._op() not implemented yet!");
return true;
});
return path;
// if (path._op(path1, path2, (int) operation)) {
// return path;
// }
// throw new UIWidgetsError("Path.combine() failed. This may be due an invalid path; " +
// "in particular, check for NaN values.");
}
public PathMetrics computeMetrics(bool forceClosed = false) {
return PathMetrics._(this, forceClosed);
}
void _appendMoveTo(float x, float y) {
this._commands.Add((float) PathCommand.moveTo);
this._commands.Add(x);

this._commandy = y;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._commandx = x;
this._commandy = y;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._expandBounds(x1, y1);
this._expandBounds(x2, y2);
this._expandBounds(x3, y3);
this._commands.Add((float) PathCommand.bezierTo);
this._commands.Add(x1);
this._commands.Add(y1);

this._commands.Add(y3);
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._commands.Add(winding);
this._pathKey = pathGlobalKey++;
this._cache = null;
}

var y0 = this._commandy;
this._appendMoveTo(x + x0, y + y0);
}

public void relativeLineTo(float x, float y) {
var x0 = this._commandx;
var y0 = this._commandy;
public void lineTo(float x, float y) {
this._appendLineTo(x, y);
}

}
this.cubicTo(x0 + c1x, y0 + c1y, x0 + c2x, y0 + c2y, x0 + x, y0 + y);
}

if (!(w > 0)) {
this.lineTo(x2, y2);
return;
}
}
}
}
if (w == 1) {
this.quadraticBezierTo(x1, y1, x2, y2);
return;

var quadX = new float[5];
var quadY = new float[5];
conic.chopIntoQuadsPOW2(quadX, quadY, 1);
this.quadraticBezierTo(quadX[1], quadY[1], quadX[2], quadY[2]);
this.quadraticBezierTo(quadX[3], quadY[3], quadX[4], quadY[4]);
}

var y0 = this._commandy;
this.conicTo(x0 + x1, y0 + y1, x0 + x2, y0 + y2, w);
}

var squareRy = ry * ry;
var squareX = transformedMidPoint.dx * transformedMidPoint.dx;
var squareY = transformedMidPoint.dy * transformedMidPoint.dy;
// Check if the radii are big enough to draw the arc, scale radii if not.
// http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
var radiiScale = squareX / squareRx + squareY / squareRy;

ry *= radiiScale;
}
var unitPts = new [] {
var unitPts = new[] {
if (!clockwise != largeArc) { // flipped from the original implementation
if (!clockwise != largeArc) {
// flipped from the original implementation
if (thetaArc < 0 && clockwise) { // arcSweep flipped from the original implementation
if (thetaArc < 0 && clockwise) {
// arcSweep flipped from the original implementation
} else if (thetaArc > 0 && !clockwise) { // arcSweep flipped from the original implementation
}
else if (thetaArc > 0 && !clockwise) {
// arcSweep flipped from the original implementation
// the arc may be slightly bigger than 1/4 circle, so allow up to 1/3rd
int segments = Mathf.CeilToInt(Mathf.Abs(thetaArc / (2 * Mathf.PI / 3)));
var thetaWidth = thetaArc / segments;

}
bool expectIntegers = ScalarUtils.ScalarNearlyZero(Mathf.PI/2 - Mathf.Abs(thetaWidth)) &&
bool expectIntegers = ScalarUtils.ScalarNearlyZero(Mathf.PI / 2 - Mathf.Abs(thetaWidth)) &&
ScalarUtils.ScalarIsInteger(rx) && ScalarUtils.ScalarIsInteger(ry) &&
ScalarUtils.ScalarIsInteger(x1) && ScalarUtils.ScalarIsInteger(y1);

unitPts[1] += centerPoint;
unitPts[0] = unitPts[1];
unitPts[0] = unitPts[0].translate(t * sinEndTheta, -t * cosEndTheta);
var mapped = new [] {
var mapped = new[] {
/*
Computing the arc width introduces rounding errors that cause arcs to start
outside their marks. A round rect may lose convexity as a result. If the input

a0 = Mathf.Atan2(dx0, -dy0);
a1 = Mathf.Atan2(-dx1, dy1);
dir = PathWinding.clockwise;
} else {
}
else {
cx = x1 + dx0 * d + -dy0 * radius;
cy = y1 + dy0 * d + dx0 * radius;
a0 = Mathf.Atan2(-dx0, dy0);

if (dir == PathWinding.clockwise) {
if (Mathf.Abs(da) >= Mathf.PI * 2) {
da = Mathf.PI * 2;
} else {
}
else {
} else {
}
else {
} else {
}
else {
// Split arc into max 90 degree segments.
int ndivs = Mathf.Max(1, Mathf.Min((int) (Mathf.Abs(da) / (Mathf.PI * 0.5f) + 0.5f), 5));
float hda = (da / ndivs) / 2.0f;

if (move == PathCommand.moveTo) {
this._appendMoveTo(x1, y1);
} else {
}
else {
} else {
}
else {
float c1x = px + ptanx;
float c1y = py + ptany;
float c2x = x - tanx;

this._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1);
}
px = x;
py = y;
ptanx = tanx;

if (points.Count == 0) {
return;
}
this._appendMoveTo(points[0].dx, points[0].dy);
for (int i = 1; i < points.Count; i++) {

this.addPath(path);
return;
}
var transform = Matrix3.makeTrans(offset.dx, offset.dy);
this.addPath(path, transform);
}

if (transform != null) {
transform.mapXY(x, y, out x, out y);
}
this._appendMoveTo(x, y);
}
i += 3;

if (transform != null) {
transform.mapXY(x, y, out x, out y);
}
this._appendLineTo(x, y);
}
i += 3;

transform.mapXY(c2x, c2y, out c2x, out c2y);
transform.mapXY(x1, y1, out x1, out y1);
}
this._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1);
}
i += 7;

return totalW != 0;
}
static int windingLine(float x0, float y0, float x1, float y1, float x, float y) {
if (y0 == y1) {
return 0;

}
}
public class PathMetrics : IEnumerable<PathMetric> {
public PathMetrics(IEnumerator<PathMetric> enumerator) {
this._enumerator = enumerator;
}
public static PathMetrics _(Path path, bool forceClosed) {
return new PathMetrics(PathMetricIterator._(new _PathMeasure())); // TODO: complete the implementation
}
public readonly IEnumerator<PathMetric> _enumerator;
public IEnumerator<PathMetric> GetEnumerator() {
return this._enumerator;
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
public class PathMetric {
// TODO
public readonly float length;
}
public class PathMetricIterator : IEnumerator<PathMetric> {
PathMetricIterator(_PathMeasure measure) {
this._pathMeasure = measure;
}
internal static PathMetricIterator _(_PathMeasure _pathMeasure) {
D.assert(_pathMeasure != null);
return new PathMetricIterator(_pathMeasure);
}
PathMetric _pathMetric;
_PathMeasure _pathMeasure;
public void Reset() {
throw new NotImplementedException();
}
public PathMetric Current {
get { return this._pathMetric; }
}
object IEnumerator.Current {
get { return this._pathMetric; }
}
public bool MoveNext() {
// if (_pathMeasure._nextContour()) {
// _pathMetric = PathMetric._(_pathMeasure);
// return true;
// }
// _pathMetric = null;
return false;
}
public void Dispose() {
throw new NotImplementedException();
}
}
class _PathMeasure {
}
public enum PathWinding {
counterClockwise = 1, // which just means the order as the input is.
clockwise = 2, // which just means the reversed order.

var closerY = Mathf.Abs(midY - startY) < Mathf.Abs(midY - endY) ? startY : endY;
c1.y2 = c2.y0 = closerY;
}
// Verify that all five points are in order.
D.assert(_between(startY, c1.y1, c1.y2));
D.assert(_between(c1.y1, c1.y2, c2.y1));

this.addPath();
this.addPoint(0, 0, PointFlags.corner);
}
ref var path = ref this._paths.array[this._paths.length - 1];
if (path.count > 0) {
ref var pt = ref this._points.array[this._points.length - 1];

y = point.y + y1,
flags = flags,
});
} else {
}
else {
this._addPoint(new PathPoint {
x = point.x + x1,
y = point.y + y1,

public void normalize() {
var points = this._points;
var paths = this._paths;
var paths = this._paths;
for (var j = 0; j < paths.length; j++) {
ref var path = ref paths.array[j];
if (path.count <= 1) {

cvertices += path.count;
}
this._vertices = new List<Vector3>(cvertices);
for (var i = 0; i < paths.length; i++) {
ref var path = ref paths.array[i];

this._expandFill();
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.length; i++) {
ref var path = ref paths.array[i];

this._expandStroke(strokeWidth, lineCap, lineJoin, miterLimit);
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.length; i++) {
ref var path = ref paths.array[i];

23
Runtime/ui/painting/txt/font_manager.cs


public class FontManager {
readonly Dictionary<string, FontInfo>[] _fonts =
new Dictionary<string, FontInfo>[9 * 2]; // max weight size x max style size
static readonly int defaultFontSize = 14;
public static readonly FontManager instance = new FontManager();

}
public void addFont(Font font, string familyName,
public void addFont(Font font, string familyName,
FontWeight fontWeight = null, FontStyle fontStyle = FontStyle.normal) {
fontWeight = fontWeight ?? FontWeight.normal;

var fonts = this._getFonts(fontWeight.index, fontStyle);
fonts.TryGetValue(familyName, out var current);
D.assert(current == null || current.font == font,
D.assert(current == null || current.font == font,
() => $"font with key {familyName} {fontWeight} {fontStyle} already exists");
var fontInfo = new FontInfo(font);
fonts[familyName] = fontInfo;

return fontInfo;
}
}
var osFont = Font.CreateDynamicFontFromOSFont(familyName, defaultFontSize);
osFont.hideFlags = HideFlags.DontSave;
osFont.material.hideFlags = HideFlags.DontSave;

}
}
public static class FontExtension
{
public static class FontExtension {
internal static bool getGlyphInfo(this Font font, char ch, out CharacterInfo info, int fontSize,
UnityEngine.FontStyle fontStyle) {
if (fontSize <= 0) {

bool success = font.GetCharacterInfo(ch, out info, fontSize, fontStyle);
if (!success) {
if (!char.IsControl(ch)) {
Debug.LogWarning(
$"character info not found from the given font: character '{ch}' (code{(int) ch}) font: ${font.name}");
D.assert(() => {
Debug.LogWarning(
$"character info not found from the given font: character '{ch}' (code{(int) ch}) font: ${font.name}");
return true;
});
}
info = default;

return true;
}
internal static void RequestCharactersInTextureSafe(this Font font, string text, int fontSize,
UnityEngine.FontStyle fontStyle = UnityEngine.FontStyle.Normal) {
internal static void RequestCharactersInTextureSafe(this Font font, string text, int fontSize,
UnityEngine.FontStyle fontStyle = UnityEngine.FontStyle.Normal) {
font.RequestCharactersInTexture(text, fontSize, fontStyle);
}
}

6
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs


using System;
using Unity.UIWidgets.foundation;
using UnityEngine;
using UnityEngine.Rendering;

mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.Zero);
}
else {
Debug.LogWarning("Not supported BlendMode: " + op + ". Defaults to srcOver");
D.assert(() => {
Debug.LogWarning("Not supported BlendMode: " + op + ". Defaults to srcOver");
return true;
});
mat.SetInt(_srcBlend, (int) UnityEngine.Rendering.BlendMode.One);
mat.SetInt(_dstBlend, (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
}

18
Runtime/ui/text.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.painting;
namespace Unity.UIWidgets.ui {
public enum FontStyle {

int? maxLines = null,
float? fontSize = null,
string fontFamily = null,
float? lineHeight = null, // todo
string ellipsis = null) {
float? height = null, // todo
string ellipsis = null,
StrutStyle strutStyle = null) {
this.textAlign = textAlign;
this.textDirection = textDirection;
this.fontWeight = fontWeight;

this.fontFamily = fontFamily;
this.lineHeight = lineHeight;
this.height = height;
this.strutStyle = strutStyle;
}
public bool Equals(ParagraphStyle other) {

return this.textAlign == other.textAlign && this.textDirection == other.textDirection &&
this.fontWeight == other.fontWeight && this.fontStyle == other.fontStyle &&
this.maxLines == other.maxLines && this.fontSize.Equals(other.fontSize) &&
string.Equals(this.fontFamily, other.fontFamily) && this.lineHeight.Equals(other.lineHeight) &&
string.Equals(this.fontFamily, other.fontFamily) && this.height.Equals(other.height) &&
string.Equals(this.ellipsis, other.ellipsis);
}

hashCode = (hashCode * 397) ^ this.maxLines.GetHashCode();
hashCode = (hashCode * 397) ^ this.fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ (this.fontFamily != null ? this.fontFamily.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ this.lineHeight.GetHashCode();
hashCode = (hashCode * 397) ^ this.height.GetHashCode();
hashCode = (hashCode * 397) ^ (this.ellipsis != null ? this.ellipsis.GetHashCode() : 0);
return hashCode;
}

fontStyle: this.fontStyle,
fontFamily: this.fontFamily,
fontSize: this.fontSize,
height: this.lineHeight
height: this.height
);
}

public readonly int? maxLines;
public readonly float? fontSize;
public readonly string fontFamily;
public readonly float? lineHeight;
public readonly float? height;
public readonly StrutStyle strutStyle;
public bool ellipsized() {
return !string.IsNullOrEmpty(this.ellipsis);

6
Runtime/ui/txt/paragraph.cs


this.Set(item.Key, item.Value, throwOnExisting: true);
}
public void AddAll(IEnumerable<TKey> list) {
foreach (var key in list) {
this.Add(new KeyValuePair<TKey, TValue>(key, default));
}
}
void Set(TKey key, TValue value, bool throwOnExisting) {
if (this.count == 0) {
this.version++;

7
Runtime/ui/window.cs


VoidCallback _onTextScaleFactorChanged;
public VoidCallback onPlatformBrightnessChanged {
get { return this._onPlatformBrightnessChanged; }
set { this._onPlatformBrightnessChanged = value; }
}
VoidCallback _onPlatformBrightnessChanged;
public FrameCallback onBeginFrame {
get { return this._onBeginFrame; }
set { this._onBeginFrame = value; }

16
Runtime/widgets/basic.cs


float textScaleFactor = 1.0f,
int? maxLines = null,
Action onSelectionChanged = null,
Color selectionColor = null
Color selectionColor = null,
StrutStyle strutStyle = null
) : base(key: key) {
D.assert(text != null);
D.assert(maxLines == null || maxLines > 0);

this.maxLines = maxLines;
this.onSelectionChanged = onSelectionChanged;
this.selectionColor = selectionColor;
this.strutStyle = strutStyle;
}
public readonly TextSpan text;

public readonly int? maxLines;
public readonly Action onSelectionChanged;
public readonly Color selectionColor;
public readonly StrutStyle strutStyle;
public override RenderObject createRenderObject(BuildContext context) {
return new RenderParagraph(

renderObject.maxLines = this.maxLines;
renderObject.onSelectionChanged = this.onSelectionChanged;
renderObject.selectionColor = this.selectionColor;
renderObject.strutStyle = this.strutStyle;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

PointerHoverEventListener onPointerHover = null,
PointerUpEventListener onPointerUp = null,
PointerCancelEventListener onPointerCancel = null,
PointerSignalEventListener onPointerSignal = null,
PointerScrollEventListener onPointerScroll = null,
PointerDragFromEditorEnterEventListener onPointerDragFromEditorEnter = null,
PointerDragFromEditorHoverEventListener onPointerDragFromEditorHover = null,

this.onPointerMove = onPointerMove;
this.onPointerUp = onPointerUp;
this.onPointerCancel = onPointerCancel;
this.onPointerSignal = onPointerSignal;
this.onPointerHover = onPointerHover;
this.onPointerExit = onPointerExit;
this.onPointerEnter = onPointerEnter;

public readonly PointerCancelEventListener onPointerCancel;
public readonly PointerSignalEventListener onPointerSignal;
public readonly PointerHoverEventListener onPointerHover;
public readonly PointerEnterEventListener onPointerEnter;

onPointerMove: this.onPointerMove,
onPointerUp: this.onPointerUp,
onPointerCancel: this.onPointerCancel,
onPointerSignal: this.onPointerSignal,
onPointerEnter: this.onPointerEnter,
onPointerExit: this.onPointerExit,
onPointerHover: this.onPointerHover,

renderObject.onPointerMove = this.onPointerMove;
renderObject.onPointerUp = this.onPointerUp;
renderObject.onPointerCancel = this.onPointerCancel;
renderObject.onPointerSignal = this.onPointerSignal;
renderObject.onPointerEnter = this.onPointerEnter;
renderObject.onPointerHover = this.onPointerHover;
renderObject.onPointerExit = this.onPointerExit;

if (this.onPointerCancel != null) {
listeners.Add("cancel");
}
if (this.onPointerSignal != null) {
listeners.Add("signal");
}
if (this.onPointerEnter != null) {

2
Runtime/widgets/dismissible.cs


Dictionary<DismissDirection?, float?> dismissThresholds = null,
TimeSpan? movementDuration = null,
float crossAxisEndOffset = 0.0f,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
D.assert(key != null);
D.assert(secondaryBackground != null ? background != null : true);

77
Runtime/widgets/editable_text.cs


public readonly TextStyle style;
public StrutStyle strutStyle {
get {
if (this._strutStyle == null) {
return this.style != null
? StrutStyle.fromTextStyle(this.style, forceStrutHeight: true)
: StrutStyle.disabled;
}
return this._strutStyle.inheritFromTextStyle(this.style);
}
}
readonly StrutStyle _strutStyle;
public readonly TextAlign textAlign;
public readonly TextDirection? textDirection;

public readonly bool unityTouchKeyboard;
public EditableText(TextEditingController controller, FocusNode focusNode, TextStyle style,
Color cursorColor, Color backgroundCursorColor = null, bool obscureText = false, bool autocorrect = false,
TextAlign textAlign = TextAlign.left, TextDirection? textDirection = null,
float? textScaleFactor = null, int? maxLines = 1,
bool autofocus = false, Color selectionColor = null, TextSelectionControls selectionControls = null,
TextInputType keyboardType = null, TextInputAction? textInputAction = null,
public EditableText(
TextEditingController controller = null,
FocusNode focusNode = null, TextStyle style = null,
StrutStyle strutStyle = null,
Color cursorColor = null,
Color backgroundCursorColor = null,
bool obscureText = false,
bool autocorrect = false,
TextAlign textAlign = TextAlign.left,
TextDirection? textDirection = null,
float? textScaleFactor = null,
int? maxLines = 1,
bool autofocus = false,
Color selectionColor = null,
TextSelectionControls selectionControls = null,
TextInputType keyboardType = null,
TextInputAction? textInputAction = null,
ValueChanged<string> onChanged = null, VoidCallback onEditingComplete = null,
ValueChanged<string> onSubmitted = null, SelectionChangedCallback onSelectionChanged = null,
List<TextInputFormatter> inputFormatters = null, bool rendererIgnoresPointer = false,
EdgeInsets scrollPadding = null, bool unityTouchKeyboard = false,
Key key = null, float? cursorWidth = 2.0f, Radius cursorRadius = null, bool cursorOpacityAnimates = false,
Offset cursorOffset = null, bool paintCursorAboveText = false,
ValueChanged<string> onChanged = null,
VoidCallback onEditingComplete = null,
ValueChanged<string> onSubmitted = null,
SelectionChangedCallback onSelectionChanged = null,
List<TextInputFormatter> inputFormatters = null,
bool rendererIgnoresPointer = false,
EdgeInsets scrollPadding = null,
bool unityTouchKeyboard = false,
Key key = null,
float? cursorWidth = 2.0f,
Radius cursorRadius = null,
bool cursorOpacityAnimates = false,
Offset cursorOffset = null,
bool paintCursorAboveText = false,
Brightness? keyboardAppearance = Brightness.light,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
bool? enableInteractiveSelection = null

this.obscureText = obscureText;
this.autocorrect = autocorrect;
this.style = style;
this._strutStyle = strutStyle;
this.textAlign = textAlign;
this.textDirection = textDirection;
this.textScaleFactor = textScaleFactor;

this._handleSelectionChanged(TextSelection.collapsed(offset: this._lastTextPosition.offset),
this.renderEditable, SelectionChangedCause.forcePress);
}
} else {
}
else {
float lerpValue = this._floatingCursorResetController.value;
float lerpX = MathUtils.lerpFloat(this._lastBoundedOffset.dx, finalPosition.dx, lerpValue);
float lerpY = MathUtils.lerpFloat(this._lastBoundedOffset.dy, finalPosition.dy, lerpValue);

public void requestKeyboard() {
if (this._hasFocus) {
this._openInputConnection();
} else {
}
else {
FocusScope.of(this.context).requestFocus(this.widget.focusNode);
}
}

get {
TextDirection? result = this.widget.textDirection ?? Directionality.of(this.context);
D.assert(result != null,
() => $"{this.GetType().FullName} created without a textDirection and with no ambient Directionality.");
() =>
$"{this.GetType().FullName} created without a textDirection and with no ambient Directionality.");
return result;
}
}

: this._cursorVisibilityNotifier,
hasFocus: this._hasFocus,
maxLines: this.widget.maxLines,
strutStyle: this.widget.strutStyle,
selectionColor: this.widget.selectionColor,
textScaleFactor: this.widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
textAlign: this.widget.textAlign,

public readonly ValueNotifier<bool> showCursor;
public readonly bool hasFocus;
public readonly int? maxLines;
public readonly StrutStyle strutStyle;
public readonly Color selectionColor;
public readonly float textScaleFactor;
public readonly TextAlign textAlign;

public _Editable(TextSpan textSpan = null, TextEditingValue value = null,
Color cursorColor = null, Color backgroundCursorColor = null, ValueNotifier<bool> showCursor = null,
bool hasFocus = false,
int? maxLines = null, Color selectionColor = null, float textScaleFactor = 1.0f,
int? maxLines = null, StrutStyle strutStyle = null, Color selectionColor = null,
float textScaleFactor = 1.0f,
TextDirection? textDirection = null, bool obscureText = false, TextAlign textAlign = TextAlign.left,
bool autocorrect = false, ViewportOffset offset = null, SelectionChangedHandler onSelectionChanged = null,
CaretChangedHandler onCaretChanged = null, bool rendererIgnoresPointer = false,

this.showCursor = showCursor;
this.hasFocus = hasFocus;
this.maxLines = maxLines;
this.strutStyle = strutStyle;
this.selectionColor = selectionColor;
this.textScaleFactor = textScaleFactor;
this.textAlign = textAlign;

backgroundCursorColor: this.backgroundCursorColor,
hasFocus: this.hasFocus,
maxLines: this.maxLines,
strutStyle: this.strutStyle,
selectionColor: this.selectionColor,
textScaleFactor: this.textScaleFactor,
textAlign: this.textAlign,

edit.showCursor = this.showCursor;
edit.hasFocus = this.hasFocus;
edit.maxLines = this.maxLines;
edit.strutStyle = this.strutStyle;
edit.selectionColor = this.selectionColor;
edit.textScaleFactor = this.textScaleFactor;
edit.textAlign = this.textAlign;

10
Runtime/widgets/fade_in_image.cs


) {
D.assert(placeholder != null);
D.assert(image != null);
D.assert(fadeOutDuration != null);
D.assert(fadeOutCurve != null);
D.assert(fadeInDuration != null);
D.assert(fadeInCurve != null);
D.assert(alignment != null);
fadeOutDuration = fadeOutDuration ?? new TimeSpan(0, 0, 0, 0, 300);
fadeOutCurve = fadeOutCurve ?? Curves.easeOut;
fadeInDuration = fadeInDuration ?? new TimeSpan(0, 0, 0, 0, 700);
fadeInCurve = Curves.easeIn;
alignment = alignment ?? Alignment.center;
var imageProvider = placeholderScale != null
? new ExactAssetImage(placeholder, bundle: bundle, scale: placeholderScale ?? 1.0f)
: (ImageProvider) new AssetImage(placeholder, bundle: bundle);

4
Runtime/widgets/form.cs


return !this.hasError;
}
bool _validate() {
void _validate() {
return !this.hasError;
}
public virtual void didChange(T value) {

53
Runtime/widgets/gesture_detector.cs


GestureTapCancelCallback onTapCancel = null,
GestureDoubleTapCallback onDoubleTap = null,
GestureLongPressCallback onLongPress = null,
GestureLongPressStartCallback onLongPressStart = null,
GestureLongPressMoveUpdateCallback onLongPressMoveUpdate = null,
GestureLongPressDragStartCallback onLongPressDragStart = null,
GestureLongPressDragUpdateCallback onLongPressDragUpdate = null,
GestureLongPressDragUpCallback onLongPressDragUp = null,
GestureLongPressEndCallback onLongPressEnd = null,
GestureDragDownCallback onVerticalDragDown = null,
GestureDragStartCallback onVerticalDragStart = null,
GestureDragUpdateCallback onVerticalDragUpdate = null,

bool haveHorizontalDrag =
onHorizontalDragStart != null || onHorizontalDragUpdate != null ||
onHorizontalDragEnd != null;
bool haveLongPress = onLongPress != null || onLongPressUp != null;
bool haveLongPressDrag = onLongPressDragStart != null || onLongPressDragUpdate != null ||
onLongPressDragUp != null;
bool havePan = onPanStart != null || onPanUpdate != null || onPanEnd != null;
bool haveScale = onScaleStart != null || onScaleUpdate != null || onScaleEnd != null;
if (havePan || haveScale) {

}
}
if (haveLongPress && haveLongPressDrag) {
throw new UIWidgetsError(
"Incorrect GestureDetector arguments.\n" +
"Having both a long press and a long press drag recognizer is " +
"redundant as the long press drag is a superset of long press. " +
"Except long press drag allows for drags after the long press is " +
"triggered."
);
}
return true;
});

this.onDoubleTap = onDoubleTap;
this.onLongPress = onLongPress;
this.onLongPressUp = onLongPressUp;
this.onLongPressDragStart = onLongPressDragStart;
this.onLongPressDragUpdate = onLongPressDragUpdate;
this.onLongPressDragUp = onLongPressDragUp;
this.onLongPressStart = onLongPressStart;
this.onLongPressMoveUpdate = onLongPressMoveUpdate;
this.onLongPressEnd = onLongPressEnd;
this.onVerticalDragDown = onVerticalDragDown;
this.onVerticalDragStart = onVerticalDragStart;
this.onVerticalDragUpdate = onVerticalDragUpdate;

public readonly GestureDoubleTapCallback onDoubleTap;
public readonly GestureLongPressCallback onLongPress;
public readonly GestureLongPressUpCallback onLongPressUp;
public readonly GestureLongPressDragStartCallback onLongPressDragStart;
public readonly GestureLongPressDragUpdateCallback onLongPressDragUpdate;
public readonly GestureLongPressDragUpCallback onLongPressDragUp;
public readonly GestureLongPressStartCallback onLongPressStart;
public readonly GestureLongPressMoveUpdateCallback onLongPressMoveUpdate;
public readonly GestureLongPressEndCallback onLongPressEnd;
public readonly GestureDragDownCallback onVerticalDragDown;
public readonly GestureDragStartCallback onVerticalDragStart;
public readonly GestureDragUpdateCallback onVerticalDragUpdate;

);
}
if (this.onLongPress != null || this.onLongPressUp != null) {
if (this.onLongPress != null ||
this.onLongPressUp != null ||
this.onLongPressStart != null ||
this.onLongPressMoveUpdate != null ||
this.onLongPressEnd != null) {
instance.onLongPressStart = this.onLongPressStart;
instance.onLongPressMoveUpdate = this.onLongPressMoveUpdate;
instance.onLongPressEnd = this.onLongPressEnd;
}
);
}
if (this.onLongPressDragStart != null || this.onLongPressDragUpdate != null ||
this.onLongPressDragUp != null) {
gestures[typeof(LongPressDragGestureRecognizer)] =
new GestureRecognizerFactoryWithHandlers<LongPressDragGestureRecognizer>(
() => new LongPressDragGestureRecognizer(debugOwner: this),
(LongPressDragGestureRecognizer instance) => {
instance.onLongPressStart = this.onLongPressDragStart;
instance.onLongPressDragUpdate = this.onLongPressDragUpdate;
instance.onLongPressUp = this.onLongPressDragUp;
}
);
}

79
Runtime/widgets/heroes.cs


public readonly bool transitionOnUserGestures;
internal static Dictionary<object, _HeroState>
_allHeroesFor(BuildContext context, bool isUserGestureTransition) {
_allHeroesFor(BuildContext context, bool isUserGestureTransition, NavigatorState navigator) {
D.assert(navigator != null);
void addHero(StatefulElement hero, object tag) {
D.assert(() => {
if (result.ContainsKey(tag)) {
throw new UIWidgetsError(
"There are multiple heroes that share the same tag within a subtree.\n" +
"Within each subtree for which heroes are to be animated (typically a PageRoute subtree), " +
"each Hero must have a unique non-null tag.\n" +
$"In this case, multiple heroes had the following tag: {tag}\n" +
"Here is the subtree for one of the offending heroes:\n" +
$"{hero.toStringDeep(prefixLineOne: "# ")}"
);
}
return true;
});
_HeroState heroState = (_HeroState) hero.state;
result[tag] = heroState;
}
void visitor(Element element) {
if (element.widget is Hero) {
StatefulElement hero = (StatefulElement) element;

D.assert(tag != null);
D.assert(() => {
if (result.ContainsKey(tag)) {
throw new UIWidgetsError(
"There are multiple heroes that share the same tag within a subtree.\n" +
"Within each subtree for which heroes are to be animated (typically a PageRoute subtree), " +
"each Hero must have a unique non-null tag.\n" +
$"In this case, multiple heroes had the following tag: {tag}\n" +
"Here is the subtree for one of the offending heroes:\n" +
$"{element.toStringDeep(prefixLineOne: "# ")}"
);
if (Navigator.of(hero) == navigator) {
addHero(hero, tag);
}
else {
ModalRoute heroRoute = ModalRoute.of(hero);
if (heroRoute != null && heroRoute is PageRoute && heroRoute.isCurrent) {
addHero(hero, tag);
return true;
});
_HeroState heroState = (_HeroState) hero.state;
result[tag] = heroState;
}
}
}

}
public override Widget build(BuildContext context) {
D.assert(context.ancestorWidgetOfExactType(typeof(Hero)) == null,
() => "A Hero widget cannot be the descendant of another Hero widget.");
if (this._placeholderSize != null) {
if (this.widget.placeholderBuilder == null) {
return new SizedBox(

HeroFlightShuttleBuilder shuttleBuilder,
bool isUserGestureTransition
) {
D.assert(this.fromHero.widget.tag == this.toHero.widget.tag);
D.assert(fromHero.widget.tag == toHero.widget.tag);
this.type = type;
this.overlay = overlay;
this.navigatorRect = navigatorRect;

}
public class HeroController : NavigatorObserver {
HeroController(CreateRectTween createRectTween) {
public HeroController(CreateRectTween createRectTween) {
this.createRectTween = createRectTween;
}

public override void didPop(Route route, Route previousRoute) {
D.assert(this.navigator != null);
D.assert(route != null);
this._maybeStartHeroTransition(route, previousRoute, HeroFlightDirection.pop, false);
if (!this.navigator.userGestureInProgress) {
this._maybeStartHeroTransition(route, previousRoute, HeroFlightDirection.pop, false);
}
}
public override void didReplace(Route newRoute = null, Route oldRoute = null) {
D.assert(this.navigator != null);
if (newRoute?.isCurrent == true) {
this._maybeStartHeroTransition(oldRoute, newRoute, HeroFlightDirection.push, false);
}
}
public override void didStartUserGesture(Route route, Route previousRoute) {

Rect navigatorRect = HeroUtils._globalBoundingBoxFor(this.navigator.context);
Dictionary<object, _HeroState>
fromHeroes = Hero._allHeroesFor(from.subtreeContext, isUserGestureTransition);
Dictionary<object, _HeroState> toHeroes = Hero._allHeroesFor(to.subtreeContext, isUserGestureTransition);
Dictionary<object, _HeroState> fromHeroes =
Hero._allHeroesFor(from.subtreeContext, isUserGestureTransition, this.navigator);
Dictionary<object, _HeroState> toHeroes =
Hero._allHeroesFor(to.subtreeContext, isUserGestureTransition, this.navigator);
if (toHeroes[tag] != null) {
if (toHeroes.ContainsKey(tag)) {
HeroFlightShuttleBuilder fromShuttleBuilder = fromHeroes[tag].widget.flightShuttleBuilder;
HeroFlightShuttleBuilder toShuttleBuilder = toHeroes[tag].widget.flightShuttleBuilder;

isUserGestureTransition: isUserGestureTransition
);
if (this._flights[tag] != null) {
this._flights[tag].divert(manifest);
if (this._flights.TryGetValue(tag, out var result)) {
result.divert(manifest);
}
else {
this._flights[tag] = new _HeroFlight(this._handleFlightEnded);

else if (this._flights[tag] != null) {
this._flights[tag].abort();
else if (this._flights.TryGetValue(tag, out var result)) {
result.abort();
}
}
}

2
Runtime/widgets/icon.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using TextStyle = Unity.UIWidgets.painting.TextStyle;

}
Widget iconWidget = new RichText(
overflow: TextOverflow.visible,
text: new TextSpan(
text: new string(new[] {(char) this.icon.codePoint}),
style: new TextStyle(

4
Runtime/widgets/nested_scroll_view.cs


ScrollPhysics physics = null,
NestedScrollViewHeaderSliversBuilder headerSliverBuilder = null,
Widget body = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
D.assert(headerSliverBuilder != null);
D.assert(body != null);

ScrollController controller,
List<Widget> slivers,
SliverOverlapAbsorberHandle handle,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
scrollDirection: scrollDirection,
reverse: reverse,

83
Runtime/widgets/overlay.cs


this.insertAll(this.widget.initialEntries);
}
public void insert(OverlayEntry entry, OverlayEntry above = null) {
D.assert(entry._overlay == null);
D.assert(above == null || (above._overlay == this && this._entries.Contains(above)));
internal int _insertionIndex(OverlayEntry below, OverlayEntry above) {
D.assert(below == null || above == null);
if (below != null) {
return this._entries.IndexOf(below);
}
if (above != null) {
return this._entries.IndexOf(above) + 1;
}
return this._entries.Count;
}
public void insert(OverlayEntry entry, OverlayEntry below = null, OverlayEntry above = null) {
D.assert(above == null || below == null, () => "Only one of `above` and `below` may be specified.");
D.assert(above == null || (above._overlay == this && this._entries.Contains(above)),
() => "The provided entry for `above` is not present in the Overlay.");
D.assert(below == null || (below._overlay == this && this._entries.Contains(below)),
() => "The provided entry for `below` is not present in the Overlay.");
D.assert(!this._entries.Contains(entry), () => "The specified entry is already present in the Overlay.");
D.assert(entry._overlay == null, () => "The specified entry is already present in another Overlay.");
this.setState(() => {
int index = above == null ? this._entries.Count : this._entries.IndexOf(above) + 1;
this._entries.Insert(index, entry);
});
this.setState(() => { this._entries.Insert(this._insertionIndex(below, above), entry); });
public void insertAll(ICollection<OverlayEntry> entries, OverlayEntry above = null) {
D.assert(above == null || (above._overlay == this && this._entries.Contains(above)));
public void insertAll(ICollection<OverlayEntry> entries, OverlayEntry below = null, OverlayEntry above = null) {
D.assert(above == null || below == null, () => "Only one of `above` and `below` may be specified.");
D.assert(above == null || (above._overlay == this && this._entries.Contains(above)),
() => "The provided entry for `above` is not present in the Overlay.");
D.assert(below == null || (below._overlay == this && this._entries.Contains(below)),
() => "The provided entry for `below` is not present in the Overlay.");
D.assert(entries.All(entry => !this._entries.Contains(entry)),
() => "One or more of the specified entries are already present in the Overlay.");
D.assert(entries.All(entry => entry._overlay == null),
() => "One or more of the specified entries are already present in another Overlay.");
if (entries.isEmpty()) {
return;
}

}
this.setState(() => {
int index = above == null ? this._entries.Count : this._entries.IndexOf(above) + 1;
this._entries.InsertRange(index, entries);
this._entries.InsertRange(this._insertionIndex(below, above), entries);
});
}
public void rearrange(IEnumerable<OverlayEntry> newEntries, OverlayEntry below = null, OverlayEntry above = null) {
List<OverlayEntry> newEntriesList =
newEntries is List<OverlayEntry> ?(newEntries as List<OverlayEntry>) : newEntries.ToList();
D.assert(above == null || below == null, () => "Only one of `above` and `below` may be specified.");
D.assert(above == null || (above._overlay == this && this._entries.Contains(above)),
() => "The provided entry for `above` is not present in the Overlay.");
D.assert(below == null || (below._overlay == this && this._entries.Contains(below)),
() => "The provided entry for `below` is not present in the Overlay.");
D.assert(newEntriesList.All(entry => !this._entries.Contains(entry)),
() => "One or more of the specified entries are already present in the Overlay.");
D.assert(newEntriesList.All(entry => entry._overlay == null),
() => "One or more of the specified entries are already present in another Overlay.");
if (newEntriesList.isEmpty()) {
return;
}
if (this._entries.SequenceEqual(newEntriesList)) {
return;
}
HashSet<OverlayEntry> old = new HashSet<OverlayEntry>(this._entries);
foreach(OverlayEntry entry in newEntriesList) {
entry._overlay = entry._overlay ?? this;
}
this.setState(() => {
this._entries.Clear();
this._entries.AddRange(newEntriesList);
foreach (OverlayEntry entry in newEntriesList) {
old.Remove(entry);
}
this._entries.InsertRange(this._insertionIndex(below, above), old);
this.setState(() => {
this._entries.Remove(entry);
});
this.setState(() => { this._entries.Remove(entry); });
}
}

7
Runtime/widgets/page_view.cs


bool pageSnapping = true,
ValueChanged<int> onPageChanged = null,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
IndexedWidgetBuilder itemBuilder = null,
SliverChildDelegate childDelegate = null,
int itemCount = 0

this.childrenDelegate = new SliverChildListDelegate(children ?? new List<Widget>());
}
}
// TODO: PageView.builder
// TODO: PageView.custom
public readonly Axis scrollDirection;

6
Runtime/widgets/routes.cs


protected internal override void install(OverlayEntry insertionPoint) {
D.assert(this._overlayEntries.isEmpty());
this._overlayEntries.AddRange(this.createOverlayEntries());
this.navigator.overlay?.insertAll(this._overlayEntries, insertionPoint);
this.navigator.overlay?.insertAll(this._overlayEntries, above: insertionPoint);
base.install(insertionPoint);
}

break;
case AnimationStatus.dismissed:
// We might still be the current route if a subclass is controlling the
// We might still be an active route if a subclass is controlling the
if (!this.isCurrent) {
if (!this.isActive) {
this.navigator.finalizeRoute(this);
D.assert(this.overlayEntries.isEmpty());
}

26
Runtime/widgets/scroll_view.cs


Key center = null,
float anchor = 0.0f,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
D.assert(!(controller != null && primary == true),
() => "Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +

float anchor = 0.0f,
float? cacheExtent = null,
List<Widget> slivers = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

bool shrinkWrap = false,
EdgeInsets padding = null,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

bool addRepaintBoundaries = true,
float? cacheExtent = null,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key,
scrollDirection: scrollDirection,
reverse: reverse,

bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) {
return new ListView(
key: key,

bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

SliverGridDelegate gridDelegate = null,
SliverChildDelegate childrenDelegate = null,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

SliverGridDelegate gridDelegate = null,
SliverChildDelegate childrenDelegate = null,
float? cacheExtent = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) {
return new GridView(
key: key,

bool addRepaintBoundaries = true,
float? cacheExtent = null,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

bool addRepaintBoundaries = true,
float? cacheExtent = null,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) {
return new GridView(
key: key,

bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(
key: key,
scrollDirection: scrollDirection,

bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
List<Widget> children = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) {
return new GridView(
key: key,

39
Runtime/widgets/scrollable.cs


using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.ui;
using UnityEngine;
namespace Unity.UIWidgets.widgets {
public delegate Widget ViewportBuilder(BuildContext context, ViewportOffset position);

ScrollController controller = null,
ScrollPhysics physics = null,
ViewportBuilder viewportBuilder = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
D.assert(viewportBuilder != null);

D.assert(this._hold == null);
D.assert(this._drag == null);
}
float _targetScrollOffsetForPointerScroll(PointerScrollEvent e) {
float delta = this.widget.axis == Axis.horizontal ? e.delta.dx : e.delta.dy;
return Mathf.Min(Mathf.Max(this.position.pixels + delta, this.position.minScrollExtent),
this.position.maxScrollExtent);
}
// TODO: float _receivedPointerSignal(PointerSignalEvent event) {
// }
void _handlePointerrScroll(PointerEvent e) {
D.assert(e is PointerScrollEvent);
float targetScrollOffset = this._targetScrollOffsetForPointerScroll(e as PointerScrollEvent);
if (targetScrollOffset != this.position.pixels) {
this.position.jumpTo(targetScrollOffset);
}
}
void _disposeHold() {
this._hold = null;

Widget result = new _ScrollableScope(
scrollable: this,
position: this.position,
child: new RawGestureDetector(
key: this._gestureDetectorKey,
gestures: this._gestureRecognizers,
behavior: HitTestBehavior.opaque,
child: new IgnorePointer(
key: this._ignorePointerKey,
ignoring: this._shouldIgnorePointer,
child: this.widget.viewportBuilder(context, this.position)
child: new Listener(
// TODO: onPointerSignal: _receivePointerSignal,
child: new RawGestureDetector(
key: this._gestureDetectorKey,
gestures: this._gestureRecognizers,
behavior: HitTestBehavior.opaque,
child: new IgnorePointer(
key: this._ignorePointerKey,
ignoring: this._shouldIgnorePointer,
child: this.widget.viewportBuilder(context, this.position)
)
)
)
);

2
Runtime/widgets/single_child_scroll_view.cs


ScrollPhysics physics = null,
ScrollController controller = null,
Widget child = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
D.assert(!(controller != null && primary == true),
() => "Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +

13
Runtime/widgets/text.cs


public Text(string data,
Key key = null,
TextStyle style = null,
StrutStyle strutStyle = null,
D.assert(data != null);
D.assert(data != null, () => "A non-null string must be provided to a Text widget.");
this.strutStyle = strutStyle;
this.textAlign = textAlign;
this.softWrap = softWrap;
this.overflow = overflow;

Text(TextSpan textSpan,
Key key = null,
TextStyle style = null,
StrutStyle strutStyle = null,
D.assert(textSpan != null);
D.assert(textSpan != null, () => "A non-null TextSpan must be provided to a Text.rich widget.");
this.strutStyle = strutStyle;
this.textAlign = textAlign;
this.softWrap = softWrap;
this.overflow = overflow;

public static Text rich(TextSpan textSpan,
Key key = null,
TextStyle style = null,
StrutStyle strutStyle = null,
TextAlign? textAlign = null,
bool? softWrap = null,
TextOverflow? overflow = null,

textSpan, key,
style,
strutStyle,
textAlign,
softWrap,
overflow,

public readonly TextStyle style;
public readonly StrutStyle strutStyle;
public readonly TextAlign? textAlign;
public readonly bool? softWrap;

overflow: this.overflow ?? defaultTextStyle.overflow,
textScaleFactor: this.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
maxLines: this.maxLines ?? defaultTextStyle.maxLines,
strutStyle: this.strutStyle,
text: new TextSpan(
style: effectiveTextStyle,
text: this.data,

179
Runtime/widgets/text_selection.cs


RenderEditable renderObject = null,
TextSelectionControls selectionControls = null,
TextSelectionDelegate selectionDelegate = null,
DragStartBehavior? dragStartBehavior = null) {
DragStartBehavior dragStartBehavior = DragStartBehavior.start) {
D.assert(value != null);
D.assert(context != null);
this.context = context;

this.selectionDelegate = selectionDelegate;
this._value = value;
OverlayState overlay = Overlay.of(context);
D.assert(overlay != null);
this._handleController = new AnimationController(duration: _fadeDuration, vsync: overlay);
this._toolbarController = new AnimationController(duration: _fadeDuration, vsync: overlay);
D.assert(overlay != null, () => $"No Overlay widget exists above {context}.\n" +
"Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your " +
"app content was created above the Navigator with the WidgetsApp builder parameter.");
this._toolbarController = new AnimationController(duration: fadeDuration, vsync: overlay);
this.dragStartBehavior = dragStartBehavior;
}

public readonly RenderEditable renderObject;
public readonly TextSelectionControls selectionControls;
public readonly TextSelectionDelegate selectionDelegate;
public readonly DragStartBehavior? dragStartBehavior;
public readonly DragStartBehavior dragStartBehavior;
public static TimeSpan _fadeDuration = TimeSpan.FromMilliseconds(150);
AnimationController _handleController;
public static readonly TimeSpan fadeDuration = TimeSpan.FromMilliseconds(150);
Animation<float> _handleOpacity {
get { return this._handleController.view; }
}
Animation<float> _toolbarOpacity {
get { return this._toolbarController.view; }

this._buildHandle(context, _TextSelectionHandlePosition.end)),
};
Overlay.of(this.context, debugRequiredFor: this.debugRequiredFor).insertAll(this._handles);
this._handleController.forward(from: 0.0f);
}
public void showToolbar() {

this._toolbar?.remove();
this._toolbar = null;
this._handleController.stop();
this._handleController.dispose();
this._toolbarController.dispose();
}

return new Container(); // hide the second handle when collapsed
}
return new FadeTransition(
opacity: this._handleOpacity,
child: new _TextSelectionHandleOverlay(
onSelectionHandleChanged: (TextSelection newSelection) => {
this._handleSelectionHandleChanged(newSelection, position);
},
onSelectionHandleTapped: this._handleSelectionHandleTapped,
layerLink: this.layerLink,
renderObject: this.renderObject,
selection: this._selection,
selectionControls: this.selectionControls,
position: position,
dragStartBehavior: this.dragStartBehavior ?? DragStartBehavior.down
)
return new _TextSelectionHandleOverlay(
onSelectionHandleChanged: (TextSelection newSelection) => {
this._handleSelectionHandleChanged(newSelection, position);
},
onSelectionHandleTapped: this._handleSelectionHandleTapped,
layerLink: this.layerLink,
renderObject: this.renderObject,
selection: this._selection,
selectionControls: this.selectionControls,
position: position,
dragStartBehavior: this.dragStartBehavior
);
}

ValueChanged<TextSelection> onSelectionHandleChanged = null,
VoidCallback onSelectionHandleTapped = null,
TextSelectionControls selectionControls = null,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
DragStartBehavior dragStartBehavior = DragStartBehavior.start
) : base(key: key) {
this.selection = selection;
this.position = position;

public override State createState() {
return new _TextSelectionHandleOverlayState();
}
internal ValueListenable<bool> _visibility {
get {
switch (this.position) {
case _TextSelectionHandlePosition.start:
return this.renderObject.selectionStartInViewport;
case _TextSelectionHandlePosition.end:
return this.renderObject.selectionEndInViewport;
}
return null;
}
}
class _TextSelectionHandleOverlayState : State<_TextSelectionHandleOverlay> {
class _TextSelectionHandleOverlayState : SingleTickerProviderStateMixin<_TextSelectionHandleOverlay> {
AnimationController _controller;
Animation<float> _opacity {
get { return this._controller.view; }
}
public override void initState() {
base.initState();
this._controller = new AnimationController(duration: TextSelectionOverlay.fadeDuration, vsync: this);
this._handleVisibilityChanged();
this.widget._visibility.addListener(this._handleVisibilityChanged);
}
void _handleVisibilityChanged() {
if (this.widget._visibility.value) {
this._controller.forward();
}
else {
this._controller.reverse();
}
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
base.didUpdateWidget(oldWidget);
(oldWidget as _TextSelectionHandleOverlay)._visibility.removeListener(this._handleVisibilityChanged);
this._handleVisibilityChanged();
this.widget._visibility.addListener(this._handleVisibilityChanged);
}
public override void dispose() {
this.widget._visibility.removeListener(this._handleVisibilityChanged);
this._controller.dispose();
base.dispose();
}
void _handleDragStart(DragStartDetails details) {
this._dragPosition = details.globalPosition +
new Offset(0.0f, -this.widget.selectionControls.handleSize.height);

break;
}
Size viewport = this.widget.renderObject.size;
point = new Offset(
point.dx.clamp(0.0f, viewport.width),
point.dy.clamp(0.0f, viewport.height)
);
child: new GestureDetector(
dragStartBehavior: this.widget.dragStartBehavior,
onPanStart: this._handleDragStart,
onPanUpdate: this._handleDragUpdate,
onTap: this._handleTap,
child: new Stack(
overflow: Overflow.visible,
children: new List<Widget>() {
new Positioned(
left: point.dx,
top: point.dy,
child: this.widget.selectionControls.buildHandle(context, type,
this.widget.renderObject.preferredLineHeight)
)
}
child: new FadeTransition(
opacity: this._opacity,
child: new GestureDetector(
dragStartBehavior: this.widget.dragStartBehavior,
onPanStart: this._handleDragStart,
onPanUpdate: this._handleDragUpdate,
onTap: this._handleTap,
child: new Stack(
overflow: Overflow.visible,
children: new List<Widget>() {
new Positioned(
left: point.dx,
top: point.dy,
child: this.widget.selectionControls.buildHandle(context, type,
this.widget.renderObject.preferredLineHeight)
)
}
)
)
)
);

GestureTapDownCallback onTapDown = null,
GestureTapUpCallback onSingleTapUp = null,
GestureTapCancelCallback onSingleTapCancel = null,
GestureLongPressCallback onSingleLongTapStart = null,
GestureLongPressStartCallback onSingleLongTapStart = null,
GestureLongPressMoveUpdateCallback onSingleLongTapMoveUpdate = null,
GestureLongPressEndCallback onSingleLongTapEnd = null,
GestureTapDownCallback onDoubleTapDown = null,
GestureDragStartCallback onDragSelectionStart = null,
DragSelectionUpdateCallback onDragSelectionUpdate = null,

public readonly GestureTapCancelCallback onSingleTapCancel;
public readonly GestureLongPressCallback onSingleLongTapStart;
public readonly GestureLongPressStartCallback onSingleLongTapStart;
public readonly GestureLongPressMoveUpdateCallback onSingleLongTapMoveUpdate;
public readonly GestureLongPressEndCallback onSingleLongTapEnd;
public readonly GestureTapDownCallback onDoubleTapDown;

this._lastDragUpdateDetails = null;
}
void _handleLongPressStart() {
void _handleLongPressStart(LongPressStartDetails details) {
this.widget.onSingleLongTapStart();
this.widget.onSingleLongTapStart(details);
}
}
void _handleLongPressMoveUpdate(LongPressMoveUpdateDetails details) {
if (!this._isDoubleTap && this.widget.onSingleLongTapMoveUpdate != null) {
this.widget.onSingleLongTapMoveUpdate(details);
void _handleLongPressEnd(LongPressEndDetails details) {
if (!this._isDoubleTap && this.widget.onSingleLongTapEnd != null) {
this.widget.onSingleLongTapEnd(details);
}
this._isDoubleTap = false;
}
void _doubleTapTimeout() {
this._doubleTapTimer = null;
this._lastTapOffset = null;

)
);
if (this.widget.onSingleLongTapStart != null) {
if (this.widget.onSingleLongTapStart != null ||
this.widget.onSingleLongTapMoveUpdate != null ||
this.widget.onSingleLongTapEnd != null
) {
instance => { instance.onLongPress = this._handleLongPressStart; });
instance => {
instance.onLongPressStart = this._handleLongPressStart;
instance.onLongPressMoveUpdate = this._handleLongPressMoveUpdate;
instance.onLongPressEnd = this._handleLongPressEnd;
});
}
if (this.widget.onDragSelectionStart != null ||

)
);
}
// TODO: if (this.widget.onForcePressStart != null || this.widget.onForcePressEnd != null) {
// }
return new RawGestureDetector(
gestures: gestures,

6
Samples/UIWidgetSample/LongPressSample.cs


class _LongPressSampleWidgetState : State<LongPressSampleWidget> {
public override Widget build(BuildContext context) {
return new GestureDetector(
onLongPressDragStart: (value) => { Debug.Log($"Long Press Drag Start: {value}"); },
onLongPressDragUpdate: (value) => { Debug.Log($"Long Press Drag Update: {value}"); },
onLongPressDragUp: (value) => { Debug.Log($"Long Press Drag Up: {value}"); },
onLongPressStart: (value) => { Debug.Log($"Long Press Drag Start: {value}"); },
onLongPressMoveUpdate: (value) => { Debug.Log($"Long Press Drag Update: {value}"); },
onLongPressEnd: (value) => { Debug.Log($"Long Press Drag Up: {value}"); },
onLongPressUp: () => { Debug.Log($"Long Press Up"); },
onLongPress: () => { Debug.Log($"Long Press"); },
child: new Center(

36
Samples/UIWidgetSample/TextInputSample.cs


protected override Widget createWidget() {
return new MaterialApp(
home: new EditableInputTypeWidget()
);
);
}

height: 80,
child: new Row(
children: new List<Widget> {
new Container(width: 100, child: new Text(title, style: new TextStyle(fontSize: 14, height: 2.0f, color: Colors.black, decoration: TextDecoration.none))),
new Container(width: 100,
child: new Text(title,
style: new TextStyle(fontSize: 14, height: 2.0f, color: Colors.black,
decoration: TextDecoration.none))),
new Flexible(child: new Container(child: widget, padding: EdgeInsets.all(4), decoration:
new BoxDecoration(border: Border.all(color: Color.black))))
}

var selectionColor = new Color(0xFF6F6F6F);
widgets.Add(this.rowWidgets("Default", new EditStateProvider(builder: ((buildContext, controller, node) =>
new EditableText(controller, node, style, cursorColor, Colors.blue,
new EditableText(controller, node, style, cursorColor: cursorColor, backgroundCursorColor: Colors.blue,
cursorWidth: 5.0f, cursorRadius: Radius.circular(2.5f), cursorOpacityAnimates: true, paintCursorAboveText: true)))));
cursorWidth: 5.0f, cursorRadius: Radius.circular(2.5f), cursorOpacityAnimates: true,
paintCursorAboveText: true)))));
new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
selectionColor: selectionColor, maxLines: 4,
onSubmitted: this.textSubmitted, unityTouchKeyboard: unityKeyboard,
selectionControls: MaterialUtils.materialTextSelectionControls)))));

new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
new EditableText(controller, node, style, cursorColor, Colors.transparent,
new EditableText(controller, node, style, cursorColor: cursorColor,
backgroundCursorColor: Colors.transparent,
selectionColor: selectionColor, keyboardType: TextInputType.url,
onSubmitted: this.textSubmitted, unityTouchKeyboard: unityKeyboard,
selectionControls: MaterialUtils.materialTextSelectionControls)))));

public override Widget build(BuildContext context) {
List<Widget> widgets = new List<Widget>();
widgets.Add(new Text("UIWidgets Touch Keyboard", style: new TextStyle(fontSize: 20, height: 2.0f, color: Colors.black, decoration: TextDecoration.none),
widgets.Add(new Text("UIWidgets Touch Keyboard",
style: new TextStyle(fontSize: 20, height: 2.0f, color: Colors.black, decoration: TextDecoration.none),
widgets.Add(new Text("Unity Touch Keyboard", style: new TextStyle(fontSize: 20, height: 2.0f, color: Colors.black, decoration: TextDecoration.none),
widgets.Add(new Text("Unity Touch Keyboard",
style: new TextStyle(fontSize: 20, height: 2.0f, color: Colors.black, decoration: TextDecoration.none),
textAlign: TextAlign.center));
widgets.AddRange(this.buildInputs(true));

5
Tests/Editor/Paragraph.cs


return null;
}
RenderBox box(RenderParagraph p, int width = 200, int height = 200) {
RenderBox box(RenderParagraph p, int width = 200, int height = 600) {
return new RenderConstrainedOverflowBox(
minWidth: width,
maxWidth: width,

child: p
)
;
);
}
RenderBox flexItemBox(RenderParagraph p, int width = 200, int height = 150) {

160
Runtime/painting/continuous_rectangle_border.cs


using System.Runtime.CompilerServices;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Rect = Unity.UIWidgets.ui.Rect;
namespace Unity.UIWidgets.painting {
public class ContinuousRectangleBorder : ShapeBorder {
public ContinuousRectangleBorder(
BorderSide side = null,
BorderRadius borderRadius = null) {
this.side = side ?? BorderSide.none;
this.borderRadius = borderRadius ?? BorderRadius.zero;
}
public readonly BorderRadius borderRadius;
public readonly BorderSide side;
public override EdgeInsets dimensions {
get {
return EdgeInsets.all(this.side.width);
}
}
public override ShapeBorder scale(float t) {
return new ContinuousRectangleBorder(
side: this.side.scale(t),
borderRadius: this.borderRadius * t
);
}
public override ShapeBorder lerpFrom(ShapeBorder a, float t) {
D.assert(t != null);
if (a is ContinuousRectangleBorder) {
return new ContinuousRectangleBorder(
side: BorderSide.lerp((a as ContinuousRectangleBorder).side, this.side, t),
borderRadius: BorderRadius.lerp((a as ContinuousRectangleBorder).borderRadius,
this.borderRadius, t)
);
}
return base.lerpFrom(a, t);
}
public override ShapeBorder lerpTo(ShapeBorder b, float t) {
D.assert(t != null);
if (b is ContinuousRectangleBorder) {
return new ContinuousRectangleBorder(
side: BorderSide.lerp(this.side, (b as ContinuousRectangleBorder).side, t),
borderRadius: BorderRadius.lerp(this.borderRadius,
(b as ContinuousRectangleBorder).borderRadius, t)
);
}
return base.lerpTo(b, t);
}
float _clampToShortest(RRect rrect, float value) {
return value > rrect.shortestSide ? rrect.shortestSide : value;
}
Path _getPath(RRect rrect) {
float left = rrect.left;
float right = rrect.right;
float top = rrect.top;
float bottom = rrect.bottom;
float tlRadiusX = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.tlRadiusX));
float tlRadiusY = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.tlRadiusY));
float trRadiusX = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.trRadiusX));
float trRadiusY = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.trRadiusY));
float blRadiusX = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.blRadiusX));
float blRadiusY = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.blRadiusY));
float brRadiusX = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.brRadiusX));
float brRadiusY = Mathf.Max(0.0f, this._clampToShortest(rrect, rrect.brRadiusY));
Path path = new Path();
path.moveTo(left, top + tlRadiusX);
path.cubicTo(left, top, left, top, left + tlRadiusY, top);
path.lineTo(right - trRadiusX, top);
path.cubicTo(right, top, right, top, right, top + trRadiusY);
path.lineTo(right, bottom - blRadiusX);
path.cubicTo(right, bottom, right, bottom, right - blRadiusY, bottom);
path.lineTo(left + brRadiusX, bottom);
path.cubicTo(left, bottom, left, bottom, left, bottom - brRadiusY);
path.close();
return path;
}
public override Path getInnerPath(Rect rect) {
return this._getPath(this.borderRadius.toRRect(rect).deflate(this.side.width));
}
public override Path getOuterPath(Rect rect) {
return this._getPath(this.borderRadius.toRRect(rect));
}
public override void paint(Canvas canvas, Rect rect) {
if (rect.isEmpty) {
return;
}
switch (this.side.style) {
case BorderStyle.none:
break;
case BorderStyle.solid:
Path path = this.getOuterPath(rect);
Paint paint = this.side.toPaint();
canvas.drawPath(path, paint);
break;
}
}
public bool Equals(ContinuousRectangleBorder other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.side == other.side && this.borderRadius == other.borderRadius;
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((ContinuousRectangleBorder) obj);
}
public override int GetHashCode() {
var hashCode = (this.side != null ? this.side.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.borderRadius != null ? this.borderRadius.GetHashCode() : 0);
return hashCode;
}
public static bool operator ==(ContinuousRectangleBorder left, ContinuousRectangleBorder right) {
return Equals(left, right);
}
public static bool operator !=(ContinuousRectangleBorder left, ContinuousRectangleBorder right) {
return !Equals(left, right);
}
public override string ToString() {
return $"{this.GetType()}({this.side}, {this.borderRadius})";
}
}
}

11
Runtime/painting/continuous_rectangle_border.cs.meta


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

220
Runtime/painting/strut_style.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.painting {
public class StrutStyle : Diagnosticable {
public StrutStyle(
string fontFamily = null,
List<string> fontFamilyFallback = null,
float? fontSize = null,
float? height = null,
float? leading = null,
FontWeight fontWeight = null,
FontStyle? fontStyle = null,
bool forceStrutHeight = false,
string debugLabel = null
) {
D.assert(fontSize == null || fontSize > 0);
D.assert(leading == null || leading >= 0);
this.fontFamily = fontFamily;
this._fontFamilyFallback = fontFamilyFallback;
this.fontSize = fontSize;
this.height = height;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.leading = leading;
this.forceStrutHeight = forceStrutHeight;
this.debugLabel = debugLabel;
}
public static StrutStyle fromTextStyle(
TextStyle textStyle,
string fontFamily = null,
List<string> fontFamilyFallback = null,
float? fontSize = null,
float? height = null,
float? leading = null,
FontWeight fontWeight = null,
FontStyle? fontStyle = null,
bool forceStrutHeight = false,
string debugLabel = null
) {
D.assert(textStyle != null);
D.assert(fontSize == null || fontSize > 0);
D.assert(leading == null || leading >= 0);
return new StrutStyle(
fontFamily: fontFamily ?? textStyle.fontFamily,
fontFamilyFallback: fontFamilyFallback ?? textStyle.fontFamilyFallback,
height: height ?? textStyle.height,
fontSize: fontSize ?? textStyle.fontSize,
fontWeight: fontWeight ?? textStyle.fontWeight,
fontStyle: fontStyle ?? textStyle.fontStyle,
debugLabel: debugLabel ?? textStyle.debugLabel
);
}
public static readonly StrutStyle disabled = new StrutStyle(
height: 0.0f,
leading: 0.0f
);
public readonly string fontFamily;
public List<string> fontFamilyFallback {
get { return this._fontFamilyFallback; }
}
readonly List<string> _fontFamilyFallback;
public readonly float? fontSize;
public readonly float? height;
public readonly FontWeight fontWeight;
public readonly FontStyle? fontStyle;
public readonly float? leading;
public readonly bool forceStrutHeight;
public readonly string debugLabel;
public RenderComparison compareTo(StrutStyle other) {
if (ReferenceEquals(this, other)) {
return RenderComparison.identical;
}
if (other == null) {
return RenderComparison.layout;
}
if (this.fontFamily != other.fontFamily ||
this.fontSize != other.fontSize ||
this.fontWeight != other.fontWeight ||
this.fontStyle != other.fontStyle ||
this.height != other.height ||
this.leading != other.leading ||
this.forceStrutHeight != other.forceStrutHeight ||
!CollectionUtils.equalsList(this.fontFamilyFallback, other.fontFamilyFallback)) {
return RenderComparison.layout;
}
return RenderComparison.identical;
}
public StrutStyle inheritFromTextStyle(TextStyle other) {
if (other == null) {
return this;
}
return new StrutStyle(
fontFamily: this.fontFamily ?? other.fontFamily,
fontFamilyFallback: this.fontFamilyFallback ?? other.fontFamilyFallback,
height: this.height ?? other.height,
leading: this.leading,
fontSize: this.fontSize ?? other.fontSize,
fontWeight: this.fontWeight ?? other.fontWeight,
fontStyle: this.fontStyle ?? other.fontStyle,
forceStrutHeight: this.forceStrutHeight,
debugLabel: this.debugLabel ?? other.debugLabel
);
}
public bool Equals(StrutStyle other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.fontFamily == other.fontFamily &&
this.fontSize == other.fontSize &&
this.fontWeight == other.fontWeight &&
this.fontStyle == other.fontStyle &&
this.height == other.height &&
this.leading == other.leading &&
this.forceStrutHeight == other.forceStrutHeight;
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((StrutStyle) obj);
}
public static bool operator ==(StrutStyle left, StrutStyle right) {
return Equals(left, right);
}
public static bool operator !=(StrutStyle left, StrutStyle right) {
return !Equals(left, right);
}
public override int GetHashCode() {
unchecked {
var hashCode = this.fontFamily?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ (this.fontSize?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ (this.fontWeight?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ (this.fontStyle?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ (this.height?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ (this.leading?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ this.forceStrutHeight.GetHashCode();
return hashCode;
}
}
public override string toStringShort() {
return $"{this.GetType()}";
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
if (this.debugLabel != null) {
properties.add(new MessageProperty("debugLabel", this.debugLabel));
}
List<DiagnosticsNode> styles = new List<DiagnosticsNode>();
styles.Add(new StringProperty("family", this.fontFamily, defaultValue: Diagnostics.kNullDefaultValue,
quoted: false));
styles.Add(new EnumerableProperty<string>("familyFallback", this.fontFamilyFallback));
styles.Add(new DiagnosticsProperty<float?>("size", this.fontSize,
defaultValue: Diagnostics.kNullDefaultValue));
string weightDescription = "";
if (this.fontWeight != null) {
weightDescription = this.fontWeight.weightValue.ToString();
}
styles.Add(new DiagnosticsProperty<FontWeight>(
"weight", this.fontWeight,
description: weightDescription,
defaultValue: Diagnostics.kNullDefaultValue
));
styles.Add(new EnumProperty<FontStyle?>("style", this.fontStyle,
defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new DiagnosticsProperty<float?>("height", this.height,
defaultValue: Diagnostics.kNullDefaultValue));
styles.Add(new FlagProperty("forceStrutHeight", value: this.forceStrutHeight,
defaultValue: Diagnostics.kNullDefaultValue));
bool styleSpecified = styles.Any((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info));
foreach (var style in styles) {
properties.add(style);
}
if (!styleSpecified) {
properties.add(new FlagProperty("forceStrutHeight", value: this.forceStrutHeight,
ifTrue: "<strut height forced>",
ifFalse: "<strut height normal>"));
}
}
}
}

11
Runtime/painting/strut_style.cs.meta


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

5
Runtime/rendering/debug.cs


namespace Unity.UIWidgets.rendering {
public static class RenderingDebugUtils {
public static bool debugCheckElevationsEnabled = false;
}
}

11
Runtime/rendering/debug.cs.meta


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