浏览代码

Merge branch 'master' of github.com:UnityTech/UIWidgets into mouse_tracking

# Conflicts:
#	Samples/UIWidgetsGallery/gallery/app.cs
/main
xingwei.zhu 5 年前
当前提交
b0400b19
共有 126 个文件被更改,包括 1659 次插入1095 次删除
  1. 7
      README-ZH.md
  2. 13
      README.md
  3. 13
      Runtime/Plugins/platform/android/view/UIWidgetsViewController.java
  4. 26
      Runtime/Plugins/platform/ios/UIWidgetsViewController.mm
  5. 14
      Runtime/Unity.UIWidgets.asmdef
  6. 12
      Runtime/animation/animation_controller.cs
  7. 2
      Runtime/animation/animations.cs
  8. 15
      Runtime/animation/tween.cs
  9. 29
      Runtime/async/timer.cs
  10. 4
      Runtime/engine/UIWidgetsMessageManager.cs
  11. 9
      Runtime/engine/UIWidgetsPanel.cs
  12. 27
      Runtime/foundation/basic_types.cs
  13. 2
      Runtime/foundation/change_notifier.cs
  14. 8
      Runtime/foundation/debug.cs
  15. 2
      Runtime/foundation/diagnostics.cs
  16. 8
      Runtime/foundation/key.cs
  17. 6
      Runtime/foundation/observer_list.cs
  18. 35
      Runtime/gestures/arena.cs
  19. 2
      Runtime/gestures/constants.cs
  20. 4
      Runtime/gestures/converter.cs
  21. 4
      Runtime/gestures/recognizer.cs
  22. 2
      Runtime/material/app_bar.cs
  23. 12
      Runtime/material/arc.cs
  24. 2
      Runtime/material/bottom_navigation_bar.cs
  25. 20
      Runtime/material/chip.cs
  26. 4
      Runtime/material/chip_theme.cs
  27. 4
      Runtime/material/expansion_panel.cs
  28. 2
      Runtime/material/flexible_space_bar.cs
  29. 2
      Runtime/material/ink_decoration.cs
  30. 8
      Runtime/material/input_decorator.cs
  31. 4
      Runtime/material/list_tile.cs
  32. 1
      Runtime/material/mergeable_material.cs
  33. 2
      Runtime/material/reorderable_list.cs
  34. 2
      Runtime/material/scaffold.cs
  35. 234
      Runtime/material/slider.cs
  36. 213
      Runtime/material/slider_theme.cs
  37. 9
      Runtime/material/text_field.cs
  38. 2
      Runtime/material/user_accounts_drawer_header.cs
  39. 17
      Runtime/painting/basic_types.cs
  40. 6
      Runtime/painting/box_border.cs
  41. 2
      Runtime/painting/box_decoration.cs
  42. 4
      Runtime/painting/decoration_image.cs
  43. 4
      Runtime/painting/gradient.cs
  44. 12
      Runtime/painting/notched_shapes.cs
  45. 16
      Runtime/rendering/box.cs
  46. 2
      Runtime/rendering/debug_overflow_indicator.cs
  47. 5
      Runtime/rendering/editable.cs
  48. 5
      Runtime/rendering/image.cs
  49. 4
      Runtime/rendering/layer.cs
  50. 6
      Runtime/rendering/object.cs
  51. 18
      Runtime/rendering/object.mixin.gen.cs
  52. 4
      Runtime/rendering/paragraph.cs
  53. 4
      Runtime/rendering/proxy_box.cs
  54. 2
      Runtime/rendering/viewport.cs
  55. 10
      Runtime/rendering/wrap.cs
  56. 17
      Runtime/scheduler/binding.cs
  57. 17
      Runtime/scheduler/ticker.cs
  58. 5
      Runtime/service/text_formatter.cs
  59. 4
      Runtime/service/text_input.cs
  60. 116
      Runtime/ui/matrix.cs
  61. 72
      Runtime/ui/painting/canvas_clip.cs
  62. 17
      Runtime/ui/painting/canvas_impl.cs
  63. 8
      Runtime/ui/painting/painting.cs
  64. 871
      Runtime/ui/painting/path.cs
  65. 1
      Runtime/ui/painting/picture.cs
  66. 2
      Runtime/ui/painting/shadow_utils.cs
  67. 65
      Runtime/ui/painting/tessellation_generator.cs
  68. 181
      Runtime/ui/painting/txt/font_manager.cs
  69. 12
      Runtime/ui/painting/txt/mesh_generator.cs
  70. 2
      Runtime/ui/text.cs
  71. 58
      Runtime/ui/txt/layout.cs
  72. 15
      Runtime/ui/txt/linebreaker.cs
  73. 4
      Runtime/ui/txt/paint_record.cs
  74. 7
      Runtime/ui/txt/paragraph.cs
  75. 4
      Runtime/ui/txt/text_buff.cs
  76. 2
      Runtime/ui/txt/wordbreaker.cs
  77. 6
      Runtime/ui/window.cs
  78. 10
      Runtime/widgets/app.cs
  79. 5
      Runtime/widgets/automatic_keep_alive.cs
  80. 34
      Runtime/widgets/basic.cs
  81. 3
      Runtime/widgets/binding.cs
  82. 2
      Runtime/widgets/container.cs
  83. 2
      Runtime/widgets/dismissible.cs
  84. 11
      Runtime/widgets/drag_target.cs
  85. 23
      Runtime/widgets/editable_text.cs
  86. 34
      Runtime/widgets/form.cs
  87. 4
      Runtime/widgets/framework.cs
  88. 84
      Runtime/widgets/gesture_detector.cs
  89. 12
      Runtime/widgets/implicit_animations.cs
  90. 4
      Runtime/widgets/localizations.cs
  91. 4
      Runtime/widgets/page_view.cs
  92. 36
      Runtime/widgets/routes.cs
  93. 2
      Runtime/widgets/scroll_activity.cs
  94. 8
      Runtime/widgets/scroll_controller.cs
  95. 2
      Runtime/widgets/scroll_position.cs
  96. 2
      Runtime/widgets/scroll_view.cs
  97. 3
      Runtime/widgets/single_child_scroll_view.cs
  98. 11
      Runtime/widgets/ticker_provider.cs
  99. 6
      Runtime/widgets/visibility.cs
  100. 80
      Samples/UIWidgetSample/MaterialSample.cs

7
README-ZH.md


当一个Unity项目运行在Android设备上时,状态栏是默认隐藏且无法在编辑内进行调整的。
如果您希望在您的UIWidgets App中显示状态栏,您可以使用这个[解决方案](https://github.com/Over17/UnityShowAndroidStatusBar)。我们将尽快推出我们自己的解决方案,并保证届时开发者可以进行无缝切换。
此外,为了让上述插件在Android P及以上Android系统中正常工作,请勾选上"Player Settings"中的"Render Outside Safe Area"选项。
#### 七、自动调节帧率
如果要使得构建出的应用能够自动调节帧率,请打开Project Settings,将构建目标平台对应的Quality选项卡中的V Sync Count设置为Don't Sync。
默认的逻辑是在界面静止时将帧率降低为25,在界面变动时将帧率提高至60。

因为浏览器中Canvas的宽高和其在显示器上的像素数可能不一致,所以构建出的WebGL程序中画面可能会模糊。
插件`Plugins/platform/webgl/UIWidgetsCanvasDevicePixelRatio.jslib`解决了这个问题。
如果您因为任何原因需要禁止此插件,请在Project面板中选中该插件,在Inspector面板中的Define Constraints参数中,输入任意(没有被Unity定义为宏)的字符串(例如`ENABLE_CANVAS_DEVICE_PIXEL_RATIO_PLUGIN`),使得只有在Player Settings中定义了这个宏,此插件才会启用。
插件`Plugins/platform/webgl/UIWidgetsCanvasDevicePixelRatio_20xx.x.jslib`(目前有2018.3和2019.1)解决了这个问题。
请根据您的项目的Unity版本选择对应的插件,并禁用此插件的其他版本。方法如下:在Project面板中选中该插件,在Inspector面板中的Select platforms for plugin中,去掉WebGL后面的对勾。
如果您因为任何原因需要完全禁止此插件的功能,请按上述方法禁用此插件的所有版本。
此插件覆盖了Unity WebGL构建模块中的如下参数:
```

13
README.md


want to show the status bar in your App, this
[solution](https://github.com/Over17/UnityShowAndroidStatusBar) seems to be
compatible to UIWidgets, therefore can be used as a good option before we release our
full support solution on this issue.
full support solution on this issue.
Besides,
please set "Render Outside Safe Area" to true in the "Player Settings" to make this plugin working properly on Android P or later.
#### Automatically Adjust Frame Rate

#### WebGL Canvas Device Pixel Ratio Plugin
The width and height of the Canvas in browser may differ from the number of pixels the Canvas occupies on the screen.
Therefore, the image may blur in the builded WebGL program.
The Plugin `Plugins/platform/webgl/UIWidgetsCanvasDevicePixelRatio.jslib` solves this issue.
If you need to disable this plugin for any reason, please select this plugin in the **Project** panel, and put an arbitrary string (that is not defined as a macro by Unity) in the **Define Constraints** field in the **Inspector** panel (for example, `ENABLE_CANVAS_DEVICE_PIXEL_RATIO_PLUGIN`), so that the plugin is enabled only if this macro is defined in **Player Settings**, which effectively disables the plugin.
The Plugin `Plugins/platform/webgl/UIWidgetsCanvasDevicePixelRatio_20xx.x.jslib` (2018.3 and 2019.1 for now) solves this issue.
Please select the plugin of the Unity version corresponding to your project, and disable other versions of this plugin, as follows: select this plugin in the **Project** panel, and uncheck **WebGL** under **Select platforms for plugin** in the **Inspector** panel.
If you need to disable this plugin for any reason, please disable all the versions of this plugin as described above.
This plugin overrides the following parameters in the Unity WebGL building module:
```

13
Runtime/Plugins/platform/android/view/UIWidgetsViewController.java


private boolean keyboardOpen;
private void setup() {
Log.i("tag", "On Setup");
//Log.i("tag", "On Setup 2");
keyboardOpen = false;
viewMetrics = new UIWidgetsViewMetrics();

} catch (Exception e) {
e.printStackTrace();
}
//Log.i("UIWidgetsDebug", " hasBar: " + hasBar);
return hasBar;
}

unityView.getWindowVisibleDisplayFrame(rect);
//Log.i("UIWidgetsDebug", "calculation: " + unityView.getRootView().getHeight() + " " + rect.bottom + " " + rect.top);
rect.bottom = unityView.getRootView().getHeight() - (rect.bottom - rect.top) - rect.top;
rect.right = unityView.getRootView().getWidth() - (rect.right - rect.left) - rect.left;

ZeroSides zeroSides = ZeroSides.NONE;
if (navigationBarHidden) {
zeroSides = calculateShouldZeroSides(unityView);
} else {
rect.bottom -= getNavigationBarHeight();
rect.bottom = rect.bottom > 0 ? rect.bottom : 0;
}
viewMetrics.padding_top = rect.top;

viewMetrics.insets_right = 0;
viewMetrics.insets_bottom = navigationBarHidden? calculateBottomKeyboardInset(rect) : rect.bottom;
viewMetrics.insets_left = 0;
//Log.i("UIWidgetsDebug", "checks: " + navigationBarHidden + " " + rect.bottom);
//Log.i("UIWidgetsDebug", " padding: " + viewMetrics.padding_top + " " + viewMetrics.padding_right + " " + viewMetrics.padding_bottom + " " + viewMetrics.padding_left);
//Log.i("UIWidgetsDebug", " insets: " + viewMetrics.insets_top + " " + viewMetrics.insets_right + " " + viewMetrics.insets_bottom + " " + viewMetrics.insets_left);
}
public void setupViewMetricsChangedListener() {

26
Runtime/Plugins/platform/ios/UIWidgetsViewController.mm


CGFloat bottom = CGRectGetHeight([[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]);
CGFloat scale = [UIScreen mainScreen].scale;
// scale == 3 => screen is 1242 * 2208 => we have to perform down-sampling to obtain the real length
// 0.8696 = 1920 / 2208, the vertical down-sampling ratio
if (scale == 3) {
bottom = bottom * 0.8696;
}
viewInsets.bottom = bottom * scale;
padding.bottom = 0;

viewMetrics metrics;
viewPadding insets = [[UIWidgetsViewController sharedInstance] viewInsets];
viewPadding padding = [[UIWidgetsViewController sharedInstance] padding];
metrics.insets_bottom = insets.bottom;
metrics.insets_top = insets.top;
metrics.insets_left = insets.left;
metrics.insets_right = insets.right;
metrics.padding_bottom = padding.bottom;
metrics.padding_top = padding.top;
metrics.padding_left = padding.left;
metrics.padding_right = padding.right;
CGFloat scale = [UIScreen mainScreen].scale;
BOOL needDownsample = scale == 3;
metrics.insets_bottom = needDownsample ? insets.bottom * 0.8696 : insets.bottom;
metrics.insets_top = needDownsample ? insets.top * 0.8696 : insets.top;
metrics.insets_left = needDownsample ? insets.left * 0.8696 : insets.left;
metrics.insets_right = needDownsample ? insets.right * 0.8696 : insets.right;
metrics.padding_bottom = needDownsample ? padding.bottom * 0.8696 : padding.bottom;
metrics.padding_top = needDownsample ? padding.top * 0.8696 : padding.top;
metrics.padding_left = needDownsample ? padding.left * 0.8696 : padding.left;
metrics.padding_right = needDownsample ? padding.right * 0.8696 : padding.right;
return metrics;
}

14
Runtime/Unity.UIWidgets.asmdef


{
"name": "Unity.UIWidgets",
"references": [],
"references": [
"Unity.InternalAPIEngineBridge.024"
],
"optionalUnityReferences": [],
"excludePlatforms": []
}
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

12
Runtime/animation/animation_controller.cs


});
D.assert(
this._ticker != null,
"AnimationController.forward() called after AnimationController.dispose()\n" +
() => "AnimationController.forward() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
this._direction = _AnimationDirection.forward;

});
D.assert(
this._ticker != null,
"AnimationController.reverse() called after AnimationController.dispose()\n" +
() => "AnimationController.reverse() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
this._direction = _AnimationDirection.reverse;

public TickerFuture animateTo(float target, TimeSpan? duration = null, Curve curve = null) {
D.assert(
this._ticker != null,
"AnimationController.animateTo() called after AnimationController.dispose()\n" +
() => "AnimationController.animateTo() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
curve = curve ?? Curves.linear;

public TickerFuture animateBack(float target, TimeSpan? duration, Curve curve = null) {
D.assert(
this._ticker != null,
"AnimationController.animateBack() called after AnimationController.dispose()\n" +
() => "AnimationController.animateBack() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
curve = curve ?? Curves.linear;

public TickerFuture animateWith(Simulation simulation) {
D.assert(
this._ticker != null,
"AnimationController.animateWith() called after AnimationController.dispose()\n" +
() => "AnimationController.animateWith() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
this.stop();

public void stop(bool canceled = true) {
D.assert(
this._ticker != null,
"AnimationController.stop() called after AnimationController.dispose()\n" +
() => "AnimationController.stop() called after AnimationController.dispose()\n" +
"AnimationController methods should not be used after calling dispose."
);
this._simulation = null;

2
Runtime/animation/animations.cs


T _lastValue;
void _maybeNotifyListeners() {
if (Equals(this.value, this._lastValue)) {
if (!Equals(this.value, this._lastValue)) {
this._lastValue = this.value;
this.notifyListeners();
}

15
Runtime/animation/tween.cs


this.end = end;
}
public T begin;
public virtual T begin { get; set; }
public T end;
public virtual T end { get; set; }
public abstract T lerp(float t);

public override int lerp(float t) {
return (this.begin + (this.end - this.begin) * t).round();
}
}
public class NullableFloatTween : Tween<float?> {
public NullableFloatTween(float? begin = null, float? end = null) : base(begin: begin, end: end) {
}
public override float? lerp(float t) {
D.assert(this.begin != null);
D.assert(this.end != null);
return this.begin + (this.end - this.begin) * t;
}
}

29
Runtime/async/timer.cs


return timer;
}
static readonly List<TimerImpl> _timers = new List<TimerImpl>();
static readonly List<TimerImpl> _appendList = new List<TimerImpl>();
List<TimerImpl> timers = null;
List<TimerImpl> appendList = null;
_timers.Clear();
_appendList.Clear();
if (timers == null) {
timers = new List<TimerImpl>();
}
timers.Add(timer);
_timers.Add(timer);
if (timers != null) {
foreach (var timer in timers) {
if (_timers.Count != 0) {
foreach (var timer in _timers) {
if (flushMicroTasks != null) {
flushMicroTasks();
}

if (appendList == null) {
appendList = new List<TimerImpl>();
}
appendList.Add(timer);
_appendList.Add(timer);
if (appendList != null) {
if (_appendList.Count != 0) {
foreach (var timer in appendList) {
foreach (var timer in _appendList) {
this._queue.enqueue(timer);
}
}

4
Runtime/engine/UIWidgetsMessageManager.cs


#endif
void OnEnable() {
D.assert(_instance == null, "Only one instance of UIWidgetsMessageManager should exists");
D.assert(_instance == null, () => "Only one instance of UIWidgetsMessageManager should exists");
D.assert(_instance != null, "_instance should not be null");
D.assert(_instance != null, () => "_instance should not be null");
_instance = null;
}

9
Runtime/engine/UIWidgetsPanel.cs


protected virtual Widget createWidget() {
return null;
}
public void recreateWidget() {
Widget root;
using (this._windowAdapter.getScope()) {
root = this.createWidget();
}
this._windowAdapter.attachRootWidget(root);
}
internal void applyRenderTexture(Rect screenRect, Texture texture, Material mat) {
this.texture = texture;

27
Runtime/foundation/basic_types.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.InternalBridge;
using UnityEngine;
using Object = UnityEngine.Object;

return "{ " + string.Join(", ", it.Select(item => item.ToString())) + " }";
}
public static void resize<T>(this List<T> list, int size, T value) {
int curSize = list.Count;
if (size < curSize) {
list.RemoveRange(size, curSize - size);
} else if(size > curSize) {
if (size > list.Capacity) {
list.Capacity = size;
}
list.AddRange(Enumerable.Repeat(value, size - curSize));
}
int remains = Math.Min(curSize, size);
for (int i = 0; i < remains; ++i) {
list[i] = value;
}
public static void reset<T>(this List<T> list, int size) {
NoAllocHelpersBridge<T>.EnsureListElemCount(list, size);
}
public static ref T refAt<T>(this List<T> list, int index) {
var array = NoAllocHelpersBridge<T>.ExtractArrayFromListT(list);
return ref array[index];
}
public static T[] array<T>(this List<T> list) {
return NoAllocHelpersBridge<T>.ExtractArrayFromListT(list);
}
}
}

2
Runtime/foundation/change_notifier.cs


this._value = value;
}
public T value {
public virtual T value {
get { return this._value; }
set {
if (Equals(value, this._value)) {

8
Runtime/foundation/debug.cs


}
[Conditional("UIWidgets_DEBUG")]
public static void assert(Func<bool> result, string message = null) {
public static void assert(Func<bool> result, Func<string> message = null) {
throw new AssertionError(message);
throw new AssertionError(message != null ? message() : "");
public static void assert(bool result, string message = null) {
public static void assert(bool result, Func<string> message = null) {
throw new AssertionError(message);
throw new AssertionError(message != null ? message() : "");
}
}

2
Runtime/foundation/diagnostics.cs


bool showSeparator = true
) {
D.assert(name == null || !name.EndsWith(":"),
"Names of diagnostic nodes must not end with colons.");
() => "Names of diagnostic nodes must not end with colons.");
this.name = name;
this._style = style;
this._showName = showName;

8
Runtime/foundation/key.cs


public static Key key(string value) {
return new ValueKey<string>(value);
}
public static bool operator ==(Key left, Key right) {
return Equals(left, right);
}
public static bool operator !=(Key left, Key right) {
return !Equals(left, right);
}
}
public abstract class LocalKey : Key {

6
Runtime/foundation/observer_list.cs


namespace Unity.UIWidgets.foundation {
public class ObserverList<T> : ICollection<T> {
public readonly List<T> _list = new List<T>();
public bool _isDirty = false;
public HashSet<T> _set = null;
readonly List<T> _list = new List<T>();
bool _isDirty = false;
HashSet<T> _set = null;
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();

35
Runtime/gestures/arena.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

}
class _GestureArena {
public List<GestureArenaMember> members = new List<GestureArenaMember>();
public readonly List<GestureArenaMember> members = new List<GestureArenaMember>();
public bool isOpen = true;
public bool isHeld = false;
public bool hasPendingSweep = false;

public GestureArenaEntry add(int pointer, GestureArenaMember member) {
_GestureArena state = this._arenas.putIfAbsent(pointer, () => {
D.assert(this._debugLogDiagnostic(pointer, "★ Opening new gesture arena."));
D.assert(this._debugLogDiagnostic(pointer, () => "★ Opening new gesture arena."));
D.assert(this._debugLogDiagnostic(pointer, $"Adding: {member}"));
D.assert(this._debugLogDiagnostic(pointer, () => $"Adding: {member}"));
return new GestureArenaEntry(this, pointer, member);
}

}
state.isOpen = false;
D.assert(this._debugLogDiagnostic(pointer, "Closing", state));
D.assert(this._debugLogDiagnostic(pointer, () => "Closing", state));
this._tryToResolveArena(pointer, state);
}

D.assert(!state.isOpen);
if (state.isHeld) {
state.hasPendingSweep = true;
D.assert(this._debugLogDiagnostic(pointer, "Delaying sweep", state));
D.assert(this._debugLogDiagnostic(pointer, () => "Delaying sweep", state));
D.assert(this._debugLogDiagnostic(pointer, "Sweeping", state));
D.assert(this._debugLogDiagnostic(pointer, () => "Sweeping", state));
pointer, $"Winner: {state.members.First()}"));
pointer, () => $"Winner: {state.members.First()}"));
state.members.First().acceptGesture(pointer);
for (int i = 1; i < state.members.Count; i++) {

}
state.isHeld = true;
D.assert(this._debugLogDiagnostic(pointer, "Holding", state));
D.assert(this._debugLogDiagnostic(pointer, () => "Holding", state));
}
public void release(int pointer) {

}
state.isHeld = false;
D.assert(this._debugLogDiagnostic(pointer, "Releasing", state));
D.assert(this._debugLogDiagnostic(pointer, () => "Releasing", state));
if (state.hasPendingSweep) {
this.sweep(pointer);
}

}
D.assert(this._debugLogDiagnostic(pointer,
$"{(disposition == GestureDisposition.accepted ? "Accepting" : "Rejecting")}: {member}"));
() => $"{(disposition == GestureDisposition.accepted ? "Accepting" : "Rejecting")}: {member}"));
D.assert(state.members.Contains(member));
if (disposition == GestureDisposition.rejected) {

}
else {
D.assert(this._debugLogDiagnostic(pointer,
$"Self-declared winner: {member}"));
() => $"Self-declared winner: {member}"));
this._resolveInFavorOf(pointer, state, member);
}
}

}
else if (state.members.isEmpty()) {
this._arenas.Remove(pointer);
D.assert(this._debugLogDiagnostic(pointer, "Arena empty."));
D.assert(this._debugLogDiagnostic(pointer, () => "Arena empty."));
$"Eager winner: {state.eagerWinner}"));
() => $"Eager winner: {state.eagerWinner}"));
this._resolveInFavorOf(pointer, state, state.eagerWinner);
}
}

D.assert(members.Count == 1);
this._arenas.Remove(pointer);
D.assert(this._debugLogDiagnostic(pointer,
$"Default winner: {state.members.First()}"));
() => $"Default winner: {state.members.First()}"));
state.members.First().acceptGesture(pointer);
}

member.acceptGesture(pointer);
}
bool _debugLogDiagnostic(int pointer, string message, _GestureArena state = null) {
bool _debugLogDiagnostic(int pointer, Func<string> message, _GestureArena state = null) {
int? count = state != null ? state.members.Count : (int?) null;
int? count = state?.members.Count;
message,
message(),
count != null ? $" with {count} member{s}." : "");
}

2
Runtime/gestures/constants.cs


public const float kPanSlop = kTouchSlop * 2.0f;
public const float kScaleSlop = kTouchSlop;
public static readonly TimeSpan kPressTimeout = new TimeSpan(0, 0, 0, 0, 100);
public static readonly TimeSpan kDoubleTapTimeout = new TimeSpan(0, 0, 0, 0, 300);

4
Runtime/gestures/converter.cs


switch (datum.change) {
case PointerChange.down: {
_PointerState state = _ensureStateForPointer(datum, position);
D.assert(!state.down);
if (state.down) {
break;
}
if (state.lastPosition != position) {
// a hover event to be here.
state.lastPosition = position;

4
Runtime/gestures/recognizer.cs


float? postAcceptSlopTolerance = Constants.kTouchSlop
) : base(debugOwner: debugOwner, kind: kind) {
D.assert(preAcceptSlopTolerance == null || preAcceptSlopTolerance >= 0,
"The preAcceptSlopTolerance must be positive or null");
() => "The preAcceptSlopTolerance must be positive or null");
"The postAcceptSlopTolerance must be positive or null");
() => "The postAcceptSlopTolerance must be positive or null");
this.deadline = deadline;
this.preAcceptSlopTolerance = preAcceptSlopTolerance;

2
Runtime/material/app_bar.cs


bool pinned = false,
bool snap = false
) : base(key: key) {
D.assert(floating || !snap, "The 'snap' argument only makes sense for floating app bars.");
D.assert(floating || !snap, () => "The 'snap' argument only makes sense for floating app bars.");
this.leading = leading;
this.automaticallyImplyLeading = true;
this.title = title;

12
Runtime/material/arc.cs


float? _endAngle;
public new Offset begin {
public override Offset begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Offset end {
public override Offset end {
get { return base.end; }
set {
if (value != base.end) {

MaterialPointArcTween _endArc;
public new Rect begin {
public override Rect begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Rect end {
public override Rect end {
get { return base.end; }
set {
if (value != base.end) {

MaterialPointArcTween _centerArc;
public new Rect begin {
public override Rect begin {
get { return base.begin; }
set {
if (value != base.begin) {

}
}
public new Rect end {
public override Rect end {
get { return base.end; }
set {
if (value != base.end) {

2
Runtime/material/bottom_navigation_bar.cs


D.assert(items != null);
D.assert(items.Count >= 2);
D.assert(items.All((BottomNavigationBarItem item) => item.title != null) == true,
"Every item must have a non-null title"
() => "Every item must have a non-null title"
);
D.assert(0 <= currentIndex && currentIndex < items.Count);
this.items = items;

20
Runtime/material/chip.cs


D.assert(label != null);
D.assert(
onPressed != null,
"Rather than disabling an ActionChip by setting onPressed to null, " +
() => "Rather than disabling an ActionChip by setting onPressed to null, " +
"remove it from the interface entirely."
);
D.assert(pressElevation == null || pressElevation >= 0.0f);

vsync: this
);
float checkmarkPercentage = ChipUtils._kCheckmarkDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float checkmarkReversePercentage = ChipUtils._kCheckmarkReverseDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float avatarDrawerReversePercentage = ChipUtils._kReverseDrawerDuration.Milliseconds /
ChipUtils._kSelectDuration.Milliseconds;
float checkmarkPercentage = (float) (ChipUtils._kCheckmarkDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
float checkmarkReversePercentage = (float) (ChipUtils._kCheckmarkReverseDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
float avatarDrawerReversePercentage = (float) (ChipUtils._kReverseDrawerDuration.TotalMilliseconds /
ChipUtils._kSelectDuration.TotalMilliseconds);
this.checkmarkAnimation = new CurvedAnimation(
parent: this.selectController,
curve: new Interval(1.0f - checkmarkPercentage, 1.0f, curve: Curves.fastOutSlowIn),

}
protected override void moveChildRenderObject(RenderObject child, object slotValue) {
D.assert(false, "not reachable");
D.assert(false, () => "not reachable");
}
}

);
this.size = this.constraints.constrain(paddedSize);
D.assert(this.size.height == this.constraints.constrainHeight(paddedSize.height),
$"Constrained height {this.size.height} doesn't match expected height " +
() => $"Constrained height {this.size.height} doesn't match expected height " +
$"Constrained width {this.size.width} doesn't match expected width " +
() => $"Constrained width {this.size.width} doesn't match expected width " +
$"{this.constraints.constrainWidth(paddedSize.width)}");
}

4
Runtime/material/chip_theme.cs


TextStyle labelStyle = null
) {
D.assert(primaryColor != null || brightness != null,
"One of primaryColor or brightness must be specified");
() => "One of primaryColor or brightness must be specified");
"Only one of primaryColor or brightness may be specified");
() => "Only one of primaryColor or brightness may be specified");
D.assert(secondaryColor != null);
D.assert(labelStyle != null);

4
Runtime/material/expansion_panel.cs


public override void initState() {
base.initState();
if (this.widget._allowOnlyOnePanelOpen) {
D.assert(this._allIdentifierUnique(), "All object identifiers are not unique!");
D.assert(this._allIdentifierUnique(), () => "All object identifiers are not unique!");
foreach (ExpansionPanelRadio child in this.widget.children) {
if (this.widget.initialOpenPanelValue != null &&
child.value == this.widget.initialOpenPanelValue) {

base.didUpdateWidget(oldWidget);
ExpansionPanelList _oldWidget = (ExpansionPanelList) oldWidget;
if (this.widget._allowOnlyOnePanelOpen) {
D.assert(this._allIdentifierUnique(), "All object identifiers are not unique!");
D.assert(this._allIdentifierUnique(), () => "All object identifiers are not unique!");
foreach (ExpansionPanelRadio newChild in this.widget.children) {
if (this.widget.initialOpenPanelValue != null &&
newChild.value == this.widget.initialOpenPanelValue) {

2
Runtime/material/flexible_space_bar.cs


FlexibleSpaceBarSettings settings =
(FlexibleSpaceBarSettings) context.inheritFromWidgetOfExactType(typeof(FlexibleSpaceBarSettings));
D.assert(settings != null,
"A FlexibleSpaceBar must be wrapped in the widget returned by FlexibleSpaceBar.createSettings().");
() => "A FlexibleSpaceBar must be wrapped in the widget returned by FlexibleSpaceBar.createSettings().");
List<Widget> children = new List<Widget>();
float deltaExtent = settings.maxExtent.Value - settings.minExtent.Value;

2
Runtime/material/ink_decoration.cs


D.assert(padding == null || padding.isNonNegative);
D.assert(decoration == null || decoration.debugAssertIsValid());
D.assert(color == null || decoration == null,
"Cannot provide both a color and a decoration\n" +
() => "Cannot provide both a color and a decoration\n" +
"The color argument is just a shorthand for \"decoration: new BoxDecoration(color: color)\".");
decoration = decoration ?? (color != null ? new BoxDecoration(color: color) : null);
this.padding = padding;

8
Runtime/material/input_decorator.cs


}
protected override float? computeDistanceToActualBaseline(TextBaseline baseline) {
D.assert(false, "not implemented");
D.assert(false, () => "not implemented");
return 0.0f;
}

}
protected override void moveChildRenderObject(RenderObject child, object slotValue) {
D.assert(false, "not reachable");
D.assert(false, () => "not reachable");
}
}

bool? alignLabelWithHint = null
) {
D.assert(enabled != null);
D.assert(!(prefix != null && prefixText != null), "Declaring both prefix and prefixText is not supported");
D.assert(!(suffix != null && suffixText != null), "Declaring both suffix and suffixText is not supported");
D.assert(!(prefix != null && prefixText != null), () => "Declaring both prefix and prefixText is not supported");
D.assert(!(suffix != null && suffixText != null), () => "Declaring both suffix and suffixText is not supported");
this.isCollapsed = false;
this.icon = icon;
this.labelText = labelText;

4
Runtime/material/list_tile.cs


}
protected override void moveChildRenderObject(RenderObject child, object slotValue) {
D.assert(false, "not reachable");
D.assert(false, () => "not reachable");
}
}

return value;
}
public new bool sizedByParent {
protected override bool sizedByParent {
get { return false; }
}

1
Runtime/material/mergeable_material.cs


using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.utils;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.material {

2
Runtime/material/reorderable_list.cs


D.assert(children != null);
D.assert(
children.All((Widget w) => w.key != null),
"All children of this widget must have a key."
() => "All children of this widget must have a key."
);
this.header = header;
this.children = children;

2
Runtime/material/scaffold.cs


ScaffoldGeometry geometry;
public new ScaffoldGeometry value {
public override ScaffoldGeometry value {
get {
D.assert(() => {
RenderObject renderObject = this.context.findRenderObject();

234
Runtime/material/slider.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;

using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Canvas = Unity.UIWidgets.ui.Canvas;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;

}
class _RenderSlider : RenderBox {
static float _positionAnimationDurationMilliSeconds = 75;
static float _minimumInteractionTimeMilliSeconds = 500;
const float _minPreferredTrackWidth = 144.0f;
public _RenderSlider(
float? value = null,
int? divisions = null,

curve: Curves.easeInOut);
}
const float _positionAnimationDurationMilliSeconds = 75;
const float _overlayRadius = 16.0f;
const float _overlayDiameter = _overlayRadius * 2.0f;
const float _trackHeight = 2.0f;
const float _preferredTrackWidth = 144.0f;
const float _preferredTotalWidth = _preferredTrackWidth + _overlayDiameter;
const float _minimumInteractionTimeMilliSeconds = 500;
static readonly Animatable<float> _overlayRadiusTween = new FloatTween(begin: 0.0f, end: _overlayRadius);
float _maxSliderPartWidth {
get {
float maxValue = 0;
foreach (Size size in this._sliderPartSizes) {
if (size.width > maxValue) {
maxValue = size.width;
}
}
return maxValue;
}
}
float _maxSliderPartHeight {
get {
float maxValue = 0;
foreach (Size size in this._sliderPartSizes) {
if (size.width > maxValue) {
maxValue = size.width;
}
}
return maxValue;
}
}
List<Size> _sliderPartSizes {
get {
return new List<Size> {
this._sliderTheme.overlayShape.getPreferredSize(this.isInteractive, this.isDiscrete),
this._sliderTheme.thumbShape.getPreferredSize(this.isInteractive, this.isDiscrete),
this._sliderTheme.tickMarkShape.getPreferredSize(isEnabled: this.isInteractive,
sliderTheme: this.sliderTheme)
};
}
}
float _minPreferredTrackHeight {
get { return this._sliderTheme.trackHeight; }
}
_SliderState _state;
Animation<float> _overlayAnimation;

bool _active = false;
float _currentDragValue = 0.0f;
float _trackLength {
get { return this.size.width - _overlayDiameter; }
Rect _trackRect {
get {
return this._sliderTheme.trackShape.getPreferredRect(
parentBox: this,
offset: Offset.zero,
sliderTheme: this._sliderTheme,
isDiscrete: false
);
}
}
bool isInteractive {

public float value {
get { return this._value; }
set {
D.assert(value != null && value >= 0.0f && value <= 1.0f);
D.assert(value >= 0.0f && value <= 1.0f);
float convertedValue = this.isDiscrete ? this._discretize(value) : value;
if (convertedValue == this._value) {
return;

float _getValueFromGlobalPosition(Offset globalPosition) {
float visualPosition =
(this.globalToLocal(globalPosition).dx - _overlayRadius) / this._trackLength;
(this.globalToLocal(globalPosition).dx - this._trackRect.left) / this._trackRect.width;
return this._getValueFromVisualPosition(visualPosition);
}

result = (result * this.divisions.Value).round() / this.divisions.Value;
result = (result * this.divisions.Value).round() * 1.0f / this.divisions.Value;
}
return result;

this._state.valueIndicatorController.status == AnimationStatus.completed) {
this._state.valueIndicatorController.reverse();
}
});
}
);
}
}
}

void _handleDragUpdate(DragUpdateDetails details) {
if (this.isInteractive) {
float valueDelta = details.primaryDelta.Value / this._trackLength;
float valueDelta = details.primaryDelta.Value / this._trackRect.width;
this._currentDragValue += valueDelta;
this.onChanged(this._discretize(this._currentDragValue));
}

protected override float computeMinIntrinsicWidth(float height) {
return Mathf.Max(_overlayDiameter,
this._sliderTheme.thumbShape.getPreferredSize(this.isInteractive, this.isDiscrete).width);
return _minPreferredTrackWidth + this._maxSliderPartWidth;
return _preferredTotalWidth;
return _minPreferredTrackWidth + this._maxSliderPartWidth;
return _overlayDiameter;
return Mathf.Max(this._minPreferredTrackHeight, this._maxSliderPartHeight);
return _overlayDiameter;
return Mathf.Max(this._minPreferredTrackHeight, this._maxSliderPartHeight);
}
protected override bool sizedByParent {

this.size = new Size(
this.constraints.hasBoundedWidth
? this.constraints.maxWidth
: _preferredTotalWidth,
: _minPreferredTrackWidth + this._maxSliderPartWidth,
: _overlayDiameter
: Mathf.Max(this._minPreferredTrackHeight, this._maxSliderPartHeight)
void _paintTickMarks(
Canvas canvas,
Rect trackLeft,
Rect trackRight,
Paint leftPaint,
Paint rightPaint) {
if (this.isDiscrete) {
const float tickRadius = _trackHeight / 2.0f;
float trackWidth = trackRight.right - trackLeft.left;
float dx = (trackWidth - _trackHeight) / this.divisions.Value;
if (dx >= 3.0 * _trackHeight) {
for (int i = 0; i <= this.divisions.Value; i += 1) {
float left = trackLeft.left + i * dx;
Offset center = new Offset(left + tickRadius, trackLeft.top + tickRadius);
if (trackLeft.contains(center)) {
canvas.drawCircle(center, tickRadius, leftPaint);
}
else if (trackRight.contains(center)) {
canvas.drawCircle(center, tickRadius, rightPaint);
}
}
}
}
}
void _paintOverlay(
Canvas canvas,
Offset center) {
Paint overlayPaint = new Paint {color = this._sliderTheme.overlayColor};
float radius = _overlayRadiusTween.evaluate(this._overlayAnimation);
canvas.drawCircle(center, radius, overlayPaint);
}
Canvas canvas = context.canvas;
float trackLength = this.size.width - 2 * _overlayRadius;
ColorTween activeTrackEnableColor = new ColorTween(begin: this._sliderTheme.disabledActiveTrackColor,
end: this._sliderTheme.activeTrackColor);
ColorTween inactiveTrackEnableColor = new ColorTween(begin: this._sliderTheme.disabledInactiveTrackColor,
end: this._sliderTheme.inactiveTrackColor);
ColorTween activeTickMarkEnableColor = new ColorTween(begin: this._sliderTheme.disabledActiveTickMarkColor,
end: this._sliderTheme.activeTickMarkColor);
ColorTween inactiveTickMarkEnableColor =
new ColorTween(begin: this._sliderTheme.disabledInactiveTickMarkColor,
end: this._sliderTheme.inactiveTickMarkColor);
Paint activeTrackPaint = new Paint {color = activeTrackEnableColor.evaluate(this._enableAnimation)};
Paint inactiveTrackPaint = new Paint {color = inactiveTrackEnableColor.evaluate(this._enableAnimation)};
Paint activeTickMarkPaint = new Paint {color = activeTickMarkEnableColor.evaluate(this._enableAnimation)};
Paint inactiveTickMarkPaint = new Paint
{color = inactiveTickMarkEnableColor.evaluate(this._enableAnimation)};
Paint leftTrackPaint = activeTrackPaint;
Paint rightTrackPaint = inactiveTrackPaint;
Paint leftTickMarkPaint = activeTickMarkPaint;
Paint rightTickMarkPaint = inactiveTickMarkPaint;
float trackRadius = _trackHeight / 2.0f;
float thumbGap = 2.0f;
Rect trackRect = this._sliderTheme.trackShape.getPreferredRect(
parentBox: this,
offset: offset,
sliderTheme: this._sliderTheme,
isDiscrete: this.isDiscrete
);
float trackVerticalCenter = offset.dy + (this.size.height) / 2.0f;
float trackLeft = offset.dx + _overlayRadius;
float trackTop = trackVerticalCenter - trackRadius;
float trackBottom = trackVerticalCenter + trackRadius;
float trackRight = trackLeft + trackLength;
float trackActive = trackLeft + trackLength * visualPosition;
float thumbRadius =
this._sliderTheme.thumbShape.getPreferredSize(this.isInteractive, this.isDiscrete).width / 2.0f;
float trackActiveLeft = Mathf.Max(0.0f,
trackActive - thumbRadius - thumbGap * (1.0f - this._enableAnimation.value));
float trackActiveRight =
Mathf.Min(trackActive + thumbRadius + thumbGap * (1.0f - this._enableAnimation.value), trackRight);
Rect trackLeftRect = Rect.fromLTRB(trackLeft, trackTop, trackActiveLeft, trackBottom);
Rect trackRightRect = Rect.fromLTRB(trackActiveRight, trackTop, trackRight, trackBottom);
Offset thumbCenter = new Offset(trackRect.left + visualPosition * trackRect.width, trackRect.center.dy);
Offset thumbCenter = new Offset(trackActive, trackVerticalCenter);
this._sliderTheme.trackShape.paint(
context,
offset,
parentBox: this,
sliderTheme: this._sliderTheme,
enableAnimation: this._enableAnimation,
thumbCenter: thumbCenter,
isDiscrete: this.isDiscrete,
isEnabled: this.isInteractive
);
if (visualPosition > 0.0) {
canvas.drawRect(trackLeftRect, leftTrackPaint);
}
if (visualPosition < 1.0) {
canvas.drawRect(trackRightRect, rightTrackPaint);
if (!this._overlayAnimation.isDismissed) {
this._sliderTheme.overlayShape.paint(
context,
thumbCenter,
activationAnimation: this._overlayAnimation,
enableAnimation: this._enableAnimation,
isDiscrete: this.isDiscrete,
labelPainter: this._labelPainter,
parentBox: this,
sliderTheme: this._sliderTheme,
value: this._value
);
this._paintOverlay(canvas, thumbCenter);
if (this.isDiscrete) {
float tickMarkWidth = this._sliderTheme.tickMarkShape.getPreferredSize(
isEnabled: this.isInteractive,
sliderTheme: this._sliderTheme
).width;
this._paintTickMarks(
canvas,
trackLeftRect,
trackRightRect,
leftTickMarkPaint,
rightTickMarkPaint
);
if ((trackRect.width - tickMarkWidth) / this.divisions.Value >= 3.0f * tickMarkWidth) {
for (int i = 0; i <= this.divisions; i++) {
float tickValue = i / this.divisions.Value;
float tickX = trackRect.left +
tickValue * (trackRect.width - tickMarkWidth) + tickMarkWidth / 2;
float tickY = trackRect.center.dy;
Offset tickMarkOffset = new Offset(tickX, tickY);
this._sliderTheme.tickMarkShape.paint(
context,
tickMarkOffset,
parentBox: this,
sliderTheme: this._sliderTheme,
enableAnimation: this._enableAnimation,
thumbCenter: thumbCenter,
isEnabled: this.isInteractive
);
}
}
}
if (this.isInteractive && this.label != null &&
this._valueIndicatorAnimation.status != AnimationStatus.dismissed) {
if (this.isInteractive && this.label != null && !this._valueIndicatorAnimation.isDismissed) {
if (this.showValueIndicator) {
this._sliderTheme.valueIndicatorShape.paint(
context,

213
Runtime/material/slider_theme.cs


public class SliderThemeData : Diagnosticable {
public SliderThemeData(
float? trackHeight = null,
Color activeTrackColor = null,
Color inactiveTrackColor = null,
Color disabledActiveTrackColor = null,

Color disabledThumbColor = null,
Color overlayColor = null,
Color valueIndicatorColor = null,
SliderTrackShape trackShape = null,
SliderTickMarkShape tickMarkShape = null,
SliderComponentShape overlayShape = null,
D.assert(trackHeight != null);
D.assert(activeTrackColor != null);
D.assert(inactiveTrackColor != null);
D.assert(disabledActiveTrackColor != null);

D.assert(disabledThumbColor != null);
D.assert(overlayColor != null);
D.assert(valueIndicatorColor != null);
D.assert(trackShape != null);
D.assert(tickMarkShape != null);
D.assert(overlayShape != null);
this.trackHeight = trackHeight.Value;
this.activeTrackColor = activeTrackColor;
this.inactiveTrackColor = inactiveTrackColor;
this.disabledActiveTrackColor = disabledActiveTrackColor;

this.disabledThumbColor = disabledThumbColor;
this.overlayColor = overlayColor;
this.valueIndicatorColor = valueIndicatorColor;
this.trackShape = trackShape;
this.tickMarkShape = tickMarkShape;
this.overlayShape = overlayShape;
this.valueIndicatorShape = valueIndicatorShape;
this.showValueIndicator = showValueIndicator.Value;
this.valueIndicatorTextStyle = valueIndicatorTextStyle;

const int overlayLightAlpha = 0x29;
return new SliderThemeData(
trackHeight: 2.0f,
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
inactiveTrackColor: primaryColor.withAlpha(inactiveTrackAlpha),
disabledActiveTrackColor: primaryColorDark.withAlpha(disabledActiveTrackAlpha),

disabledThumbColor: primaryColorDark.withAlpha(disabledThumbAlpha),
overlayColor: primaryColor.withAlpha(overlayLightAlpha),
valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha),
trackShape: new RectangularSliderTrackShape(),
tickMarkShape: new RoundSliderTickMarkShape(),
overlayShape: new RoundSliderOverlayShape(),
public readonly float trackHeight;
public readonly Color activeTrackColor;

public readonly Color valueIndicatorColor;
public readonly SliderTrackShape trackShape;
public readonly SliderTickMarkShape tickMarkShape;
public readonly SliderComponentShape overlayShape;
public readonly SliderComponentShape thumbShape;
public readonly SliderComponentShape valueIndicatorShape;

TextStyle valueIndicatorTextStyle = null
) {
return new SliderThemeData(
trackHeight: trackHeight ?? this.trackHeight,
activeTrackColor: activeTrackColor ?? this.activeTrackColor,
inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor,
disabledActiveTrackColor: disabledActiveTrackColor ?? this.disabledActiveTrackColor,

disabledThumbColor: disabledThumbColor ?? this.disabledThumbColor,
overlayColor: overlayColor ?? this.overlayColor,
valueIndicatorColor: valueIndicatorColor ?? this.valueIndicatorColor,
trackShape: trackShape ?? this.trackShape,
tickMarkShape: tickMarkShape ?? this.tickMarkShape,
overlayShape: overlayShape ?? this.overlayShape,
valueIndicatorShape: valueIndicatorShape ?? this.valueIndicatorShape,
showValueIndicator: showValueIndicator ?? this.showValueIndicator,
valueIndicatorTextStyle: valueIndicatorTextStyle ?? this.valueIndicatorTextStyle

D.assert(a != null);
D.assert(b != null);
return new SliderThemeData(
trackHeight: MathUtils.lerpFloat(a.trackHeight, b.trackHeight, t),
activeTrackColor: Color.lerp(a.activeTrackColor, b.activeTrackColor, t),
inactiveTrackColor: Color.lerp(a.inactiveTrackColor, b.inactiveTrackColor, t),
disabledActiveTrackColor: Color.lerp(a.disabledActiveTrackColor, b.disabledActiveTrackColor, t),

disabledThumbColor: Color.lerp(a.disabledThumbColor, b.disabledThumbColor, t),
overlayColor: Color.lerp(a.overlayColor, b.overlayColor, t),
valueIndicatorColor: Color.lerp(a.valueIndicatorColor, b.valueIndicatorColor, t),
trackShape: t < 0.5 ? a.trackShape : b.trackShape,
tickMarkShape: t < 0.5 ? a.tickMarkShape : b.tickMarkShape,
overlayShape: t < 0.5 ? a.overlayShape : b.overlayShape,
valueIndicatorShape: t < 0.5 ? a.valueIndicatorShape : b.valueIndicatorShape,
showValueIndicator: t < 0.5 ? a.showValueIndicator : b.showValueIndicator,
valueIndicatorTextStyle: TextStyle.lerp(a.valueIndicatorTextStyle, b.valueIndicatorTextStyle, t)

return true;
}
return other.activeTrackColor == this.activeTrackColor
return other.trackHeight == this.trackHeight
&& other.activeTrackColor == this.activeTrackColor
&& other.inactiveTrackColor == this.inactiveTrackColor
&& other.disabledActiveTrackColor == this.disabledActiveTrackColor
&& other.disabledInactiveTrackColor == this.disabledInactiveTrackColor

&& other.disabledThumbColor == this.disabledThumbColor
&& other.overlayColor == this.overlayColor
&& other.valueIndicatorColor == this.valueIndicatorColor
&& other.trackShape == this.trackShape
&& other.tickMarkShape == this.tickMarkShape
&& other.overlayShape == this.overlayShape
&& other.valueIndicatorShape == this.valueIndicatorShape
&& other.showValueIndicator == this.showValueIndicator
&& other.valueIndicatorTextStyle == this.valueIndicatorTextStyle;

}
unchecked {
var hashCode = this.activeTrackColor.GetHashCode();
var hashCode = this.trackHeight.GetHashCode();
hashCode = (hashCode * 397) ^ this.activeTrackColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.inactiveTrackColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.disabledActiveTrackColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.disabledInactiveTrackColor.GetHashCode();

hashCode = (hashCode * 397) ^ this.disabledThumbColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.overlayColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.valueIndicatorColor.GetHashCode();
hashCode = (hashCode * 397) ^ this.trackShape.GetHashCode();
hashCode = (hashCode * 397) ^ this.tickMarkShape.GetHashCode();
hashCode = (hashCode * 397) ^ this.overlayShape.GetHashCode();
hashCode = (hashCode * 397) ^ this.valueIndicatorShape.GetHashCode();
hashCode = (hashCode * 397) ^ this.showValueIndicator.GetHashCode();
hashCode = (hashCode * 397) ^ this.valueIndicatorTextStyle.GetHashCode();

defaultValue: defaultData.overlayColor, level: DiagnosticLevel.debug));
properties.add(new DiagnosticsProperty<Color>("valueIndicatorColor", this.valueIndicatorColor,
defaultValue: defaultData.valueIndicatorColor));
properties.add(new DiagnosticsProperty<SliderTrackShape>("trackShape", this.trackShape,
defaultValue: defaultData.trackShape, level: DiagnosticLevel.debug));
properties.add(new DiagnosticsProperty<SliderTickMarkShape>("tickMarkShape", this.tickMarkShape,
defaultValue: defaultData.tickMarkShape, level: DiagnosticLevel.debug));
properties.add(new DiagnosticsProperty<SliderComponentShape>("overlayShape", this.overlayShape,
defaultValue: defaultData.overlayShape, level: DiagnosticLevel.debug));
properties.add(new DiagnosticsProperty<SliderComponentShape>("valueIndicatorShape",
this.valueIndicatorShape, defaultValue: defaultData.valueIndicatorShape, level: DiagnosticLevel.debug));
properties.add(new EnumProperty<ShowValueIndicator>("showValueIndicator", this.showValueIndicator,

public abstract void paint(
PaintingContext context,
Offset thumbCenter,
Offset center,
Animation<float> activationAnimation = null,
Animation<float> enableAnimation = null,
bool? isDiscrete = null,

public override void paint(
PaintingContext context,
Offset thumbCenter,
Offset center,
Animation<float> activationAnimation = null,
Animation<float> enableAnimation = null,
bool? isDiscrete = null,

}
}
public class RectangularSliderTrackShape : SliderTrackShape {
public RectangularSliderTrackShape(
float disabledThumbGapWidth = 2.0f) {
this.disabledThumbGapWidth = disabledThumbGapWidth;
}
public readonly float disabledThumbGapWidth;
public override Rect getPreferredRect(
RenderBox parentBox = null,
Offset offset = null,
SliderThemeData sliderTheme = null,
bool? isEnabled = null,
bool? isDiscrete = null) {
float overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
float trackHeight = sliderTheme.trackHeight;
D.assert(overlayWidth >= 0);
D.assert(trackHeight >= 0);
D.assert(parentBox.size.width >= overlayWidth);
D.assert(parentBox.size.height >= trackHeight);
float trackLeft = offset.dx + overlayWidth / 2f;
float trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2f;
float trackWidth = parentBox.size.width - overlayWidth;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
public override void paint(
PaintingContext context,
Offset offset,
RenderBox parentBox = null,
SliderThemeData sliderTheme = null,
Animation<float> enableAnimation = null,
Offset thumbCenter = null,
bool? isEnabled = null,
bool? isDiscrete = null) {
if (sliderTheme.trackHeight == 0) {
return;
}
ColorTween activeTrackColorTween = new ColorTween(begin: sliderTheme.disabledActiveTrackColor,
end: sliderTheme.activeTrackColor);
ColorTween inactiveTrackColorTween = new ColorTween(begin: sliderTheme.disabledInactiveTrackColor,
end: sliderTheme.inactiveTrackColor);
Paint activePaint = new Paint {color = activeTrackColorTween.evaluate(enableAnimation)};
Paint inactivePaint = new Paint {color = inactiveTrackColorTween.evaluate(enableAnimation)};
Paint leftTrackPaint = activePaint;
Paint rightTrackPaint = inactivePaint;
float horizontalAdjustment = 0.0f;
if (!isEnabled.Value) {
float disabledThumbRadius = sliderTheme.thumbShape.getPreferredSize(false, isDiscrete).width / 2.0f;
float gap = this.disabledThumbGapWidth * (1.0f - enableAnimation.value);
horizontalAdjustment = disabledThumbRadius + gap;
}
Rect trackRect = this.getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete
);
Rect leftTrackSegment = Rect.fromLTRB(trackRect.left, trackRect.top, thumbCenter.dx - horizontalAdjustment,
trackRect.bottom);
context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + horizontalAdjustment, trackRect.top,
trackRect.right, trackRect.bottom);
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
}
}
public class RoundSliderTickMarkShape : SliderTickMarkShape {
public RoundSliderTickMarkShape(
float? tickMarkRadius = null) {
this.tickMarkRadius = tickMarkRadius;
}
public readonly float? tickMarkRadius;
public override Size getPreferredSize(
SliderThemeData sliderTheme = null,
bool? isEnabled = null
) {
return Size.fromRadius(this.tickMarkRadius ?? sliderTheme.trackHeight / 2f);
}
public override void paint(
PaintingContext context,
Offset center,
RenderBox parentBox = null,
SliderThemeData sliderTheme = null,
Animation<float> enableAnimation = null,
Offset thumbCenter = null,
bool? isEnabled = null
) {
Color begin;
Color end;
bool isTickMarkRightOfThumb = center.dx > thumbCenter.dx;
begin = isTickMarkRightOfThumb
? sliderTheme.disabledInactiveTickMarkColor
: sliderTheme.disabledActiveTickMarkColor;
end = isTickMarkRightOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
Paint paint = new Paint {color = new ColorTween(begin: begin, end: end).evaluate(enableAnimation)};
float tickMarkRadius = this.getPreferredSize(
isEnabled: isEnabled,
sliderTheme: sliderTheme
).width / 2f;
context.canvas.drawCircle(center, tickMarkRadius, paint);
}
}
public class RoundSliderThumbShape : SliderComponentShape {
public RoundSliderThumbShape(
float enabledThumbRadius = 6.0f,

}
}
public class RoundSliderOverlayShape : SliderComponentShape {
public RoundSliderOverlayShape(
float overlayRadius = 16.0f) {
this.overlayRadius = overlayRadius;
}
public readonly float overlayRadius;
public override Size getPreferredSize(bool? isEnabled, bool? isDiscrete) {
return Size.fromRadius(this.overlayRadius);
}
public override void paint(
PaintingContext context,
Offset center,
Animation<float> activationAnimation = null,
Animation<float> enableAnimation = null,
bool? isDiscrete = null,
TextPainter labelPainter = null,
RenderBox parentBox = null,
SliderThemeData sliderTheme = null,
float? value = null
) {
Canvas canvas = context.canvas;
FloatTween radiusTween = new FloatTween(
begin: 0.0f,
end: this.overlayRadius
);
canvas.drawCircle(
center,
radiusTween.evaluate(activationAnimation),
new Paint {color = sliderTheme.overlayColor}
);
}
}
public class PaddleSliderValueIndicatorShape : SliderComponentShape {
public PaddleSliderValueIndicatorShape() {
}

const float _bottomLobeRadius = 6.0f;
const float _bottomLobeStartAngle = -1.1f * Mathf.PI / 4.0f;
const float _bottomLobeEndAngle = 1.1f * 5 * Mathf.PI / 4.0f;
const float _bottomLobeEndAngle = 1.1f * 5f * Mathf.PI / 4.0f;
const float _labelPadding = 8.0f;
const float _distanceBetweenTopBottomCenters = 40.0f;
static readonly Offset _topLobeCenter = new Offset(0.0f, -_distanceBetweenTopBottomCenters);

if (!_debuggingLabelLocation) {
return true;
}
Offset leftCenter = _topLobeCenter - new Offset(leftWidthNeeded, 0.0f) + neckStretch;
Offset rightCenter = _topLobeCenter + new Offset(rightWidthNeeded, 0.0f) + neckStretch;
Rect valueRect = Rect.fromLTRB(

9
Runtime/material/text_field.cs


properties.add(new EnumProperty<TextCapitalization>("textCapitalization", this.textCapitalization, defaultValue: TextCapitalization.none));
properties.add(new EnumProperty<TextAlign>("textAlign", this.textAlign, defaultValue: TextAlign.left));
properties.add(new EnumProperty<TextDirection>("textDirection", this.textDirection, defaultValue: null));
properties.add(new FloatProperty("cursorWidth", this.cursorWidth, defaultValue: 2.0));
properties.add(new FloatProperty("cursorWidth", this.cursorWidth, defaultValue: 2.0f));
properties.add(new DiagnosticsProperty<Radius>("cursorRadius", this.cursorRadius, defaultValue: null));
properties.add(new DiagnosticsProperty<Color>("cursorColor", this.cursorColor, defaultValue: null));
properties.add(new DiagnosticsProperty<Brightness?>("keyboardAppearance", this.keyboardAppearance, defaultValue: null));

return effectiveDecoration.copyWith(counter: counter);
}
if (this.widget.maxLength == null)
if (this.widget.maxLength == null) {
}
if (this.widget.maxLength > 0) {
counterText += $"/{this.widget.maxLength}";

D.assert(
!(this.widget.style != null && this.widget.style.inherit == false &&
(this.widget.style.fontSize == null || this.widget.style.textBaseline == null)),
"inherit false style must supply fontSize and textBaseline"
() => "inherit false style must supply fontSize and textBaseline"
);
ThemeData themeData = Theme.of(context);
TextStyle style = themeData.textTheme.subhead.merge(this.widget.style);

2
Runtime/material/user_accounts_drawer_header.cs


right: 0.0f,
child: new Row(
children: (this.otherAccountsPictures ?? new List<Widget> { })
.GetRange(0, Math.Min(3, this.otherAccountsPictures?.Count ?? 0))
.GetRange(0, Mathf.Min(3, this.otherAccountsPictures?.Count ?? 0))
.Select<Widget, Widget>(
(Widget picture) => {
return new Padding(

17
Runtime/painting/basic_types.cs


using System;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.painting {
public enum RenderComparison {

right,
down,
left,
}
public static class AxisDirectionUtils {
public static AxisDirection? getAxisDirectionFromAxisReverseAndDirectionality(
BuildContext context,
Axis axis,
bool reverse) {
switch (axis) {
case Axis.horizontal:
return reverse ? AxisDirection.left : AxisDirection.right;
case Axis.vertical:
return reverse ? AxisDirection.up : AxisDirection.down;
}
return null;
}
}
public static class AxisUtils {

6
Runtime/painting/box_border.cs


switch (shape) {
case BoxShape.circle:
D.assert(borderRadius == null,
"A borderRadius can only be given for rectangular boxes.");
() => "A borderRadius can only be given for rectangular boxes.");
_paintUniformBorderWithCircle(canvas, rect, this.top);
break;
case BoxShape.rectangle:

}
}
D.assert(borderRadius == null, "A borderRadius can only be given for uniform borders.");
D.assert(shape == BoxShape.rectangle, "A border can only be drawn as a circle if it is uniform.");
D.assert(borderRadius == null, () => "A borderRadius can only be given for uniform borders.");
D.assert(shape == BoxShape.rectangle, () => "A border can only be drawn as a circle if it is uniform.");
BorderUtils.paintBorder(canvas, rect,
top: this.top, right: this.right, bottom: this.bottom, left: this.left);

2
Runtime/painting/box_decoration.cs


) {
D.assert(
backgroundBlendMode == null || color != null || gradient != null,
"backgroundBlendMode applies to BoxDecoration\'s background color or " +
() => "backgroundBlendMode applies to BoxDecoration\'s background color or " +
"gradient, but no color or gradient was provided."
);

4
Runtime/painting/decoration_image.cs


fit = fit ?? (centerSlice == null ? BoxFit.scaleDown : BoxFit.fill);
D.assert(centerSlice == null || (fit != BoxFit.none && fit != BoxFit.cover),
$"centerSlice was used with a BoxFit {fit} that is not supported.");
() => $"centerSlice was used with a BoxFit {fit} that is not supported.");
FittedSizes fittedSizes = FittedSizes.applyBoxFit(fit.Value, inputSize / scale, outputSize);
Size sourceSize = fittedSizes.source * scale;
Size destinationSize = fittedSizes.destination;

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) {

4
Runtime/painting/gradient.cs


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.");
() => "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>();

return null;
}
D.assert(this.colors.Count >= 2, "colors list must have at least two colors");
D.assert(this.colors.Count >= 2, () => "colors list must have at least two colors");
float separation = 1.0f / (this.colors.Count - 1);
return Enumerable.Range(0, this.colors.Count).Select(i => i * separation).ToList();

12
Runtime/painting/notched_shapes.cs


float notchRadius = guest.width / 2.0f;
const float s1 = 15.0f;
const float s2 = 1.0f;

float p2yA = Mathf.Sqrt(r * r - p2xA * p2xA);
float p2yB = Mathf.Sqrt(r * r - p2xB * p2xB);
List<Offset> p = new List<Offset>(6);
Offset[] p = new Offset[6];
p[0] = new Offset(a - s1, b);
p[1] = new Offset(a, b);

p[4] = new Offset(-1.0f * p[1].dx, p[1].dy);
p[5] = new Offset(-1.0f * p[0].dx, p[0].dy);
for (int i = 0; i < p.Count; i += 1) {
for (int i = 0; i < p.Length; i += 1) {
p[i] += guest.center;
}

ret.quadraticBezierTo(p[1].dx, p[1].dy, p[2].dx, p[2].dy);
// TODO: replace this lineTo() with arcToPoint when arcToPoint is ready
ret.lineTo(p[3].dx, p[3].dy);
// ret.arcToPoint(p[3], p[3], radius: Radius.circular(notchRadius), clockwise: false);
ret.arcToPoint(
p[3],
radius: Radius.circular(notchRadius),
clockwise: false);
ret.quadraticBezierTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy);
ret.lineTo(host.right, host.top);
ret.lineTo(host.right, host.bottom);

16
Runtime/rendering/box.cs


D.assert(
(a.minWidth.isFinite() && b.minWidth.isFinite()) ||
(a.minWidth == float.PositiveInfinity && b.minWidth == float.PositiveInfinity),
"Cannot interpolate between finite constraints and unbounded constraints.");
() => "Cannot interpolate between finite constraints and unbounded constraints.");
"Cannot interpolate between finite constraints and unbounded constraints.");
() => "Cannot interpolate between finite constraints and unbounded constraints.");
"Cannot interpolate between finite constraints and unbounded constraints.");
() => "Cannot interpolate between finite constraints and unbounded constraints.");
"Cannot interpolate between finite constraints and unbounded constraints.");
() => "Cannot interpolate between finite constraints and unbounded constraints.");
return new BoxConstraints(
minWidth: a.minWidth.isFinite()
? MathUtils.lerpFloat(a.minWidth, b.minWidth, t)

public Size size {
get {
D.assert(this.hasSize, "RenderBox was not laid out: " + this);
D.assert(this.hasSize, () => "RenderBox was not laid out: " + this);
D.assert(() => {
if (this._size is _DebugSize) {
_DebugSize _size = (_DebugSize) this._size;

public float? getDistanceToBaseline(TextBaseline baseline, bool onlyReal = false) {
D.assert(!_debugDoingBaseline,
"Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
() => "Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
D.assert(!this.debugNeedsLayout);
D.assert(() => {
RenderObject parent = (RenderObject) this.parent;

public virtual float? getDistanceToActualBaseline(TextBaseline baseline) {
D.assert(_debugDoingBaseline,
"Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
() => "Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
this._cachedBaselines = this._cachedBaselines ?? new Dictionary<TextBaseline, float?>();
return this._cachedBaselines.putIfAbsent(baseline, () => this.computeDistanceToActualBaseline(baseline));

D.assert(_debugDoingBaseline,
"Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
() => "Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.");
return null;
}

2
Runtime/rendering/debug_overflow_indicator.cs


string overflowText = "";
D.assert(overflows.isNotEmpty(),
$"Somehow {renderObject.GetType()} didn't actually overflow like it thought it did.");
() => $"Somehow {renderObject.GetType()} didn't actually overflow like it thought it did.");
switch (overflows.Count) {
case 1:
overflowText = overflows.first();

5
Runtime/rendering/editable.cs


public TextPosition getParagraphBackward(TextPosition position, TextAffinity? affinity = null) {
var lineCount = this._textPainter.getLineCount();
Paragraph.LineRange line = null;
for (int i = lineCount - 1; i >= 0; --i) {
line = this._textPainter.getLineRange(i);

int baseOffset = fromPosition.offset;
int extentOffset = fromPosition.offset;
if (toPosition != null) {
baseOffset = Math.Min(fromPosition.offset, toPosition.offset);
extentOffset = Math.Max(fromPosition.offset, toPosition.offset);
baseOffset = Mathf.Min(fromPosition.offset, toPosition.offset);
extentOffset = Mathf.Max(fromPosition.offset, toPosition.offset);
}
TextSelection newSelection = new TextSelection(

5
Runtime/rendering/image.cs


ColorFilter _colorFilter;
void _updateColorFilter() {
if (this._color == null)
if (this._color == null) {
else
} else {
}
}
Color _color;

4
Runtime/rendering/layer.cs


}
D.assert(this.link.leader.owner == this.owner,
"Linked LeaderLayer anchor is not in the same layer tree as the FollowerLayer.");
() => "Linked LeaderLayer anchor is not in the same layer tree as the FollowerLayer.");
"LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.");
() => "LeaderLayer anchor must come before FollowerLayer in paint order, but the reverse was true.");
HashSet<Layer> ancestors = new HashSet<Layer>();
Layer ancestor = this.parent;

6
Runtime/rendering/object.cs


if (needsCompositing) {
var inverse = Matrix3.I();
var invertible = effectiveTransform.invert(inverse);
D.assert(invertible);
// it could just be "scale == 0", ignore the assertion.
// D.assert(invertible);
this.pushLayer(
new TransformLayer(effectiveTransform),

public OffsetLayer layer {
get {
D.assert(this.isRepaintBoundary,
"You can only access RenderObject.layer for render objects that are repaint boundaries.");
() => "You can only access RenderObject.layer for render objects that are repaint boundaries.");
D.assert(!this._needsPaint);
return this._layer;

18
Runtime/rendering/object.mixin.gen.cs


}
public virtual void insert(ChildType child, ChildType after = null) {
D.assert(child != this, "A RenderObject cannot be inserted into itself.");
D.assert(child != this, () => "A RenderObject cannot be inserted into itself.");
"A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, "A RenderObject cannot be inserted after itself.");
() => "A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, () => "A RenderObject cannot be inserted after itself.");
D.assert(child != this._firstChild);
D.assert(child != this._lastChild);

}
public virtual void insert(ChildType child, ChildType after = null) {
D.assert(child != this, "A RenderObject cannot be inserted into itself.");
D.assert(child != this, () => "A RenderObject cannot be inserted into itself.");
"A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, "A RenderObject cannot be inserted after itself.");
() => "A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, () => "A RenderObject cannot be inserted after itself.");
D.assert(child != this._firstChild);
D.assert(child != this._lastChild);

}
public virtual void insert(ChildType child, ChildType after = null) {
D.assert(child != this, "A RenderObject cannot be inserted into itself.");
D.assert(child != this, () => "A RenderObject cannot be inserted into itself.");
"A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, "A RenderObject cannot be inserted after itself.");
() => "A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.");
D.assert(child != after, () => "A RenderObject cannot be inserted after itself.");
D.assert(child != this._firstChild);
D.assert(child != this._lastChild);

4
Runtime/rendering/paragraph.cs


int baseOffset = fromPosition.offset;
int extentOffset = fromPosition.offset;
if (toPosition != null) {
baseOffset = Math.Min(fromPosition.offset, toPosition.offset);
extentOffset = Math.Max(fromPosition.offset, toPosition.offset);
baseOffset = Mathf.Min(fromPosition.offset, toPosition.offset);
extentOffset = Mathf.Max(fromPosition.offset, toPosition.offset);
}
TextSelection newSelection = new TextSelection(

4
Runtime/rendering/proxy_box.cs


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");
D.assert(context.canvas == canvas, () => "canvas changed even though needsCompositing was false");
}
}
}

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");
D.assert(context.canvas == canvas, () => "canvas changed even though needsCompositing was false");
}
}
}

2
Runtime/rendering/viewport.cs


RenderBox pivot = null;
bool onlySlivers = target is RenderSliver;
while (child.parent != this) {
D.assert(child.parent != null, $"target must be a descendant of ${this}");
D.assert(child.parent != null, () => $"target must be a descendant of ${this}");
if (child is RenderBox) {
pivot = (RenderBox) child;
}

10
Runtime/rendering/wrap.cs


}
}
public bool _debugHasNecessaryDirections {
bool _debugHasNecessaryDirections {
get {
if (this.firstChild != null && this.lastChild != this.firstChild) {
// i.e. there"s more than one child

"Horizontal $runtimeType with multiple children has a null textDirection, so the layout order is undefined.");
() => $"Horizontal {this.GetType()} with multiple children has a null textDirection, so the layout order is undefined.");
break;
case Axis.vertical:
break;

switch (this.direction) {
case Axis.horizontal:
D.assert(this.textDirection != null,
"Horizontal $runtimeType with alignment $alignment has a null textDirection, so the alignment cannot be resolved.");
() => $"Horizontal {this.GetType()} with alignment {this.alignment} has a null textDirection, so the alignment cannot be resolved.");
break;
case Axis.vertical:
break;

break;
case Axis.vertical:
D.assert(this.textDirection != null,
"Vertical $runtimeType with runAlignment $runAlignment has a null textDirection, so the alignment cannot be resolved.");
() => $"Vertical {this.GetType()} with runAlignment {this.runAlignment} has a null textDirection, so the alignment cannot be resolved.");
break;
}
}

break;
case Axis.vertical:
D.assert(this.textDirection != null,
"Vertical $runtimeType with crossAxisAlignment $crossAxisAlignment has a null textDirection, so the alignment cannot be resolved.");
() => $"Vertical {this.GetType()} with crossAxisAlignment {this.crossAxisAlignment} has a null textDirection, so the alignment cannot be resolved.");
break;
}
}

17
Runtime/scheduler/binding.cs


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using RSG.Promises;
using Unity.UIWidgets.foundation;

});
this.debugStack = debugCurrentCallbackStack;
} else {
this.debugStack = new StackTrace(2, true);
this.debugStack = "skipped, use StackTraceUtility.ExtractStackTrace() if you need it"; // StackTraceUtility.ExtractStackTrace();
}
return true;

public readonly FrameCallback callback;
public static StackTrace debugCurrentCallbackStack;
public StackTrace debugStack;
internal static string debugCurrentCallbackStack;
internal string debugStack;
}
public enum SchedulerPhase {

public static SchedulerBinding instance {
get {
D.assert(_instance != null,
"Binding.instance is null. " +
() => "Binding.instance is null. " +
"This usually happens when there is a callback from outside of UIWidgets. " +
"Try to use \"using (WindowProvider.of(BuildContext).getScope()) { ... }\" to wrap your code.");
return _instance;

if (value == null) {
D.assert(_instance != null, "Binding.instance is already cleared.");
D.assert(_instance != null, () => "Binding.instance is already cleared.");
D.assert(_instance == null, "Binding.instance is already assigned.");
D.assert(_instance == null, () => "Binding.instance is already assigned.");
_instance = value;
}
}

buffer.Append("ms");
}
void _invokeFrameCallback(FrameCallback callback, TimeSpan timeStamp, StackTrace callbackStack = null) {
void _invokeFrameCallback(FrameCallback callback, TimeSpan timeStamp, string callbackStack = null) {
D.assert(callback != null);
D.assert(_FrameCallbackEntry.debugCurrentCallbackStack == null);
D.assert(() => {

"When the scheduler callback was _registered_ (as opposed to when the " +
"exception was thrown), this was the stack:"
);
UIWidgetsError.defaultStackFilter(callbackStack.ToString().TrimEnd().Split('\n'))
UIWidgetsError.defaultStackFilter(callbackStack.TrimEnd().Split('\n'))
.Each((line) => information.AppendLine(line));
}
));

17
Runtime/scheduler/ticker.cs


using System;
using System.Diagnostics;
using System.Text;
using RSG;
using RSG.Promises;

}
public class Ticker {
public Ticker(TickerCallback onTick, string debugLabel = null) {
public Ticker(TickerCallback onTick, Func<string> debugLabel = null) {
this._debugCreationStack = new StackTrace();
this._debugCreationStack = "skipped, use StackTraceUtility.ExtractStackTrace() if you need it"; // StackTraceUtility.ExtractStackTrace();
return true;
});
this._onTick = onTick;

D.assert(this._startTime == null);
D.assert(this._animationId == null);
D.assert((originalTicker._future == null) == (originalTicker._startTime == null),
"Cannot absorb Ticker after it has been disposed.");
() => "Cannot absorb Ticker after it has been disposed.");
if (originalTicker._future != null) {
this._future = originalTicker._future;
this._startTime = originalTicker._startTime;

});
}
public readonly string debugLabel;
internal readonly Func<string> debugLabel;
StackTrace _debugCreationStack;
string _debugCreationStack;
public override string ToString() {
return this.toString(debugIncludeStack: false);

var buffer = new StringBuilder();
buffer.Append(this.GetType() + "(");
D.assert(() => {
buffer.Append(this.debugLabel ?? "");
if (this.debugLabel != null) {
buffer.Append(this.debugLabel());
}
return true;
});
buffer.Append(')');

buffer.AppendLine("The stack trace when the " + this.GetType() + " was actually created was:");
UIWidgetsError.defaultStackFilter(this._debugCreationStack.ToString().TrimEnd().Split('\n'))
UIWidgetsError.defaultStackFilter(this._debugCreationStack.TrimEnd().Split('\n'))
.Each(line => buffer.AppendLine(line));
}

5
Runtime/service/text_formatter.cs


using System;
using System.Text.RegularExpressions;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.service {
public abstract class TextInputFormatter {

public override TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
if (this.maxLength != null && this.maxLength > 0 && newValue.text.Length > this.maxLength) {
TextSelection newSelection = newValue.selection.copyWith(
baseOffset: Math.Min(newValue.selection.start, this.maxLength.Value),
extentOffset: Math.Min(newValue.selection.end, this.maxLength.Value)
baseOffset: Mathf.Min(newValue.selection.start, this.maxLength.Value),
extentOffset: Mathf.Min(newValue.selection.end, this.maxLength.Value)
);
string truncated = newValue.text.Substring(0, this.maxLength.Value);

4
Runtime/service/text_input.cs


public static RawFloatingCursorPoint _toTextPoint(FloatingCursorDragState state,
Dictionary<string, float?> encoded) {
D.assert(encoded.getOrDefault("X") != null,
"You must provide a value for the horizontal location of the floating cursor.");
() => "You must provide a value for the horizontal location of the floating cursor.");
"You must provide a value for the vertical location of the floating cursor.");
() => "You must provide a value for the vertical location of the floating cursor.");
Offset offset = state == FloatingCursorDragState.Update
? new Offset(encoded["X"] ?? 0.0f, encoded["Y"] ?? 0.0f)
: new Offset(0, 0);

116
Runtime/ui/matrix.cs


}
public Offset mapXY(float x, float y) {
Offset result;
this.getMapXYProc()(this, x, y, out result);
return result;
this.getMapXYProc()(this, x, y, out var x1, out var y1);
return new Offset(x1, y1);
}
public void mapXY(float x, float y, out float x1, out float y1) {
this.getMapXYProc()(this, x, y, out x1, out y1);
}
public bool mapRect(out Rect dst, Rect src) {

return true;
}
else {
var points = new[] {
this.mapXY(src.left, src.top),
this.mapXY(src.right, src.top),
this.mapXY(src.right, src.bottom),
this.mapXY(src.left, src.bottom),
};
float x1, y1, x2, y2, x3, y3, x4, y4;
this.mapXY(src.left, src.top, out x1, out y1);
this.mapXY(src.right, src.top, out x2, out y2);
this.mapXY(src.right, src.bottom, out x3, out y3);
this.mapXY(src.left, src.bottom, out x4, out y4);
var minX = points[0].dx;
var minY = points[0].dy;
var maxX = points[0].dx;
var maxY = points[0].dy;
var minX = x1;
var minY = y1;
var maxX = x1;
var maxY = y1;
for (int i = 1; i < 4; ++i) {
minX = Mathf.Min(minX, points[i].dx);
minY = Mathf.Min(minY, points[i].dy);
maxX = Mathf.Max(maxX, points[i].dx);
maxY = Mathf.Max(maxY, points[i].dy);
if (x2 < minX) {
minX = x2;
}
if (x2 > maxX) {
maxX = x2;
}
if (y2 < minY) {
minY = y2;
}
if (y2 > maxY) {
maxY = y2;
}
if (x3 < minX) {
minX = x3;
}
if (x3 > maxX) {
maxX = x3;
}
if (y3 < minY) {
minY = y3;
}
if (y3 > maxY) {
maxY = y3;
}
if (x4 < minX) {
minX = x4;
}
if (x4 > maxX) {
maxX = x4;
}
if (y4 < minY) {
minY = y4;
}
if (y4 > maxY) {
maxY = y4;
}
dst = Rect.fromLTRB(minX, minY, maxX, maxY);

}
}
delegate void MapXYProc(Matrix3 mat, float x, float y, out Offset result);
delegate void MapXYProc(Matrix3 mat, float x, float y, out float x1, out float y1);
static readonly MapXYProc[] gMapXYProcs = {
Identity_xy, Trans_xy,

return GetMapXYProc(this.getType());
}
static void Identity_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void Identity_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(sx, sy);
resX = sx;
resY = sy;
static void Trans_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void Trans_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(sx + m.fMat[kMTransX], sy + m.fMat[kMTransY]);
resX = sx + m.fMat[kMTransX];
resY = sy + m.fMat[kMTransY];
static void Scale_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void Scale_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(sx * m.fMat[kMScaleX], sy * m.fMat[kMScaleY]);
resX = sx * m.fMat[kMScaleX];
resY = sy * m.fMat[kMScaleY];
static void ScaleTrans_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void ScaleTrans_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(sx * m.fMat[kMScaleX] + m.fMat[kMTransX],
sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
resX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
resY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
static void Rot_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void Rot_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(
ScalarUtils.sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]),
ScalarUtils.sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]));
resX = ScalarUtils.sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]);
resY = ScalarUtils.sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]);
static void RotTrans_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void RotTrans_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
result = new Offset(
ScalarUtils.sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX],
ScalarUtils.sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]);
resX = ScalarUtils.sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
resY = ScalarUtils.sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
static void Persp_xy(Matrix3 m, float sx, float sy, out Offset result) {
static void Persp_xy(Matrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert(m.hasPerspective());
float x = ScalarUtils.sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) +

z = 1 / z;
}
result = new Offset(x * z, y * z);
resX = x * z;
resY = y * z;
}
delegate void MapPtsProc(Matrix3 mat, Offset[] dst, Offset[] src, int count);

public static bool ScalarNearlyEqual(float x, float y, float tolerance = kScalarNearlyZero) {
D.assert(tolerance >= 0);
return Mathf.Abs(x - y) <= tolerance;
}
public static bool ScalarIsInteger(float scalar) {
return scalar == Mathf.FloorToInt(scalar);
}
public static float DegreesToRadians(float degrees) {

72
Runtime/ui/painting/canvas_clip.cs


return this._genId;
}
// bool _convexContains(float x, float y) {
// if (this.mesh.vertices.Count <= 2) {
// return false;
// }
//
// if (this.mesh.matrix != null) {
// if (this._invMat == null) {
// this._invMat = Matrix3.I();
// this.mesh.matrix.invert(this._invMat); // ignore if not invertible for now.
// }
//
// var offset = this._invMat.mapXY(x, y);
// x = offset.dx;
// y = offset.dy;
// }
//
// for (var i = 0; i < this.mesh.vertices.Count; i++) {
// var p0 = this.mesh.vertices[i];
// var p1 = this.mesh.vertices[i == this.mesh.vertices.Count - 1 ? 0 : i + 1];
//
// if (PathUtils.triarea2(p0.x, p0.y, p1.x, p1.y, x, y) < 0.0f) {
// return false;
// }
// }
//
// return true;
// }
bool _convexContains(Rect rect) {
if (this.mesh.vertices.Count <= 2) {
return false;
}
for (var i = 0; i < this.mesh.vertices.Count; i++) {
var p1 = this.mesh.vertices[i];
var p0 = this.mesh.vertices[i == this.mesh.vertices.Count - 1 ? 0 : i + 1];
var v = p1 - p0;
if (v.x == 0.0 && v.y == 0.0) {
continue;
}
float yL = v.y * (rect.left - p0.x);
float xT = v.x * (rect.top - p0.y);
float yR = v.y * (rect.right - p0.x);
float xB = v.x * (rect.bottom - p0.y);
if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
return false;
}
}
return true;
}
public bool contains(Rect rect) {
if (this.isRect) {

// this seems to be inefficient. disable it for now.
// if (this.convex) {
// return this._convexContains(rect.left, rect.top) &&
// this._convexContains(rect.left, rect.bottom) &&
// this._convexContains(rect.right, rect.top) &&
// this._convexContains(rect.right, rect.bottom);
// }
if (this.convex) {
if (this.mesh.matrix != null && !this.mesh.matrix.isIdentity()) {
if (this._invMat == null) {
this._invMat = Matrix3.I();
this.mesh.matrix.invert(this._invMat); // ignore if not invertible for now.
}
rect = this._invMat.mapRect(rect);
}
return this._convexContains(rect);
}
return false;
}

17
Runtime/ui/painting/canvas_impl.cs


// request font texture so text mesh could be generated correctly
var style = textBlob.style;
var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily, style.fontWeight, style.fontStyle).font;
var font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
var fontSizeToLoad = Mathf.CeilToInt(style.UnityFontSize * scale);
var subText = textBlob.text.Substring(textBlob.textOffset, textBlob.textSize);
font.RequestCharactersInTextureSafe(subText, fontSizeToLoad, style.UnityFontStyle);

D.assert(this._layers[0].states.Count == 1);
var layer = this._currentLayer;
if (layer.draws.Count == 0) {
D.assert(layer.layers.Count == 0);
return;
}
using (var cmdBuf = new CommandBuffer()) {
cmdBuf.name = "CommandBufferCanvas";

toClear = false;
}
}
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) {
bool toClear = true;

}
break;
case CmdScissor cmd:
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
if (cmd.deviceScissor == null) {
cmdBuf.DisableScissorRect();
} else {

}
}
if (toClear) {
this._setRenderTarget(cmdBuf, layer.rtID, ref toClear);
}
D.assert(!toClear);
foreach (var subLayer in layer.layers) {
cmdBuf.ReleaseTemporaryRT(subLayer.rtID);

8
Runtime/ui/painting/painting.cs


namespace Unity.UIWidgets.ui {
class PaintingUtils {
internal static bool _offsetIsValid(Offset offset) {
D.assert(offset != null, "Offset argument was null.");
D.assert(!offset.dx.isNaN() && !offset.dy.isNaN(), "Offset argument contained a NaN value.");
D.assert(offset != null, () => "Offset argument was null.");
D.assert(!offset.dx.isNaN() && !offset.dy.isNaN(), () => "Offset argument contained a NaN value.");
D.assert(radius != null, "Radius argument was null.");
D.assert(!radius.x.isNaN() && !radius.y.isNaN(), "Radius argument contained a NaN value.");
D.assert(radius != null, () => "Radius argument was null.");
D.assert(!radius.x.isNaN() && !radius.y.isNaN(), () => "Radius argument contained a NaN value.");
return true;
}

871
Runtime/ui/painting/path.cs
文件差异内容过多而无法显示
查看文件

1
Runtime/ui/painting/picture.cs


paint.strokeMiterLimit).transform(state.xform);
}
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
float sigma = scale * paint.maskFilter.sigma;
float sigma3 = 3 * sigma;

2
Runtime/ui/painting/shadow_utils.cs


namespace Unity.UIWidgets.ui {
static class ShadowUtils {
public static bool kUseFastShadow = true;
public static bool kUseFastShadow = false;
public const float kAmbientHeightFactor = 1.0f / 128.0f;
public const float kAmbientGeomFactor = 64.0f;

65
Runtime/ui/painting/tessellation_generator.cs


return true;
}
return this.x2.Equals(other.x2) && this.y2.Equals(other.y2) && this.x3.Equals(other.x3) &&
this.y3.Equals(other.y3) && this.x4.Equals(other.x4) && this.y4.Equals(other.y4) &&
this.tessTol.Equals(other.tessTol);
return this.x2 == other.x2 && this.y2 == other.y2 && this.x3 == other.x3 &&
this.y3 == other.y3 && this.x4 == other.x4 && this.y4 == other.y4 &&
this.tessTol == other.tessTol;
}
public override bool Equals(object obj) {

return this.Equals((TessellationKey) obj);
}
public override int GetHashCode() {
public override unsafe int GetHashCode() {
var hashCode = this.x2.GetHashCode();
hashCode = (hashCode * 397) ^ this.y2.GetHashCode();
hashCode = (hashCode * 397) ^ this.x3.GetHashCode();
hashCode = (hashCode * 397) ^ this.y3.GetHashCode();
hashCode = (hashCode * 397) ^ this.x4.GetHashCode();
hashCode = (hashCode * 397) ^ this.y4.GetHashCode();
hashCode = (hashCode * 397) ^ this.tessTol.GetHashCode();
var hashCode = 0;
float x = this.x2;
hashCode ^= *(int*) &x;
x = this.y2;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.x3;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.y3;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.x4;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.y4;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.tessTol;
hashCode = (hashCode * 13) ^ *(int*) &x;
return hashCode;
}
}

}
}
public static List<PathPoint> tessellateBezier(float x1, float y1, float x2, float y2,
public static List<Vector2> tessellateBezier(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4, float tessTol) {
var key = new TessellationKey(x1, y1, x2, y2, x3, y3, x4, y4, tessTol);

return _toPathPoints(tessellationInfo.points, x1, y1);
return tessellationInfo.points;
return _toPathPoints(points, x1, y1);
}
static List<PathPoint> _toPathPoints(List<Vector2> points, float x1, float y1) {
var pathPoints = new List<PathPoint>(points.Count);
foreach (var point in points) {
pathPoints.Add(new PathPoint {
x = point.x + x1,
y = point.y + y1,
});
}
return pathPoints;
return points;
}
struct _StackData {

public float y4;
public int level;
}
static readonly Stack<_StackData> _stack = new Stack<_StackData>();
static List<Vector2> _tessellateBezier(
float x1, float y1, float x2, float y2,

var points = new List<Vector2>();
var stack = new Stack<_StackData>();
stack.Push(new _StackData {
_stack.Clear();
_stack.Push(new _StackData {
while (stack.Count > 0) {
var stackData = stack.Pop();
while (_stack.Count > 0) {
var stackData = _stack.Pop();
x1 = stackData.x1;
y1 = stackData.y1;
x2 = stackData.x2;

float y1234 = (y123 + y234) * 0.5f;
if (level < 10) {
stack.Push(new _StackData {
_stack.Push(new _StackData {
stack.Push(new _StackData {
_stack.Push(new _StackData {
x1 = x1, y1 = y1, x2 = x12, y2 = y12, x3 = x123, y3 = y123, x4 = x1234, y4 = y1234,
level = level + 1,
});

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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;

}
}
class FontRef : IEquatable<FontRef> {
public readonly string familyName;
public readonly FontWeight fontWeight;
public readonly FontStyle fontStyle;
public FontRef(string familyName, FontWeight fontWeight, FontStyle fontStyle) {
this.familyName = familyName;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
}
public bool Equals(FontRef other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return string.Equals(this.familyName, other.familyName) && this.fontWeight == other.fontWeight && this.fontStyle == other.fontStyle;
}
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((FontRef) obj);
}
public override int GetHashCode() {
unchecked {
var hashCode = (this.familyName != null ? this.familyName.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (this.fontWeight != null ? this.fontWeight.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (int) this.fontStyle;
return hashCode;
}
}
public static bool operator ==(FontRef left, FontRef right) {
return Equals(left, right);
}
public static bool operator !=(FontRef left, FontRef right) {
return !Equals(left, right);
}
public override string ToString() {
return $"{nameof(this.familyName)}: {this.familyName}, {nameof(this.fontWeight)}: {this.fontWeight}, {nameof(this.fontStyle)}: {this.fontStyle}";
}
}
readonly Dictionary<FontRef, FontInfo> _fonts = new Dictionary<FontRef, FontInfo>();
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,
FontWeight fontWeight = null, FontStyle fontStyle = FontStyle.normal) {
if (fontWeight == null) {
fontWeight = FontWeight.normal;
}
fontWeight = fontWeight ?? FontWeight.normal;
FontRef fontRef = new FontRef(familyName, fontWeight, fontStyle);
D.assert(font.dynamic, $"adding font which is not dynamic is not allowed {font.name}");
D.assert(font.dynamic, () => $"adding font which is not dynamic is not allowed {font.name}");
FontInfo current;
this._fonts.TryGetValue(fontRef, out current);
D.assert(current == null || current.font == font, $"font with key {fontRef} already exists");
var fonts = this._getFonts(fontWeight.index, fontStyle);
fonts.TryGetValue(familyName, out var current);
D.assert(current == null || current.font == font,
() => $"font with key {familyName} {fontWeight} {fontStyle} already exists");
this._fonts[fontRef] = fontInfo;
fonts[familyName] = fontInfo;
}
Dictionary<string, FontInfo> _getFonts(int fontWeight, FontStyle fontStyle) {
var index = fontWeight * 2 + (int) fontStyle;
var fonts = this._fonts[index];
if (fonts == null) {
fonts = this._fonts[index] = new Dictionary<string, FontInfo>();
}
return fonts;
if (fontWeight == null) {
fontWeight = FontWeight.normal;
}
FontRef fontRef = new FontRef(familyName, fontWeight, fontStyle);
if (this._fonts.TryGetValue(fontRef, out var fontInfo)) {
fontWeight = fontWeight ?? FontWeight.normal;
var fonts = this._getFonts(fontWeight.index, fontStyle);
if (fonts.TryGetValue(familyName, out var fontInfo)) {
if (fontWeight != FontWeight.normal || fontStyle != FontStyle.normal) {
if (fontWeight.index != FontWeight.normal.index || fontStyle != FontStyle.normal) {
fontInfo = this.getOrCreate(familyName, FontWeight.normal, FontStyle.normal);
if (fontInfo != null) {
return fontInfo;

osFont.material.mainTexture.hideFlags = HideFlags.DontSave;
var newFont = new FontInfo(osFont);
fontRef = new FontRef(familyName, fontWeight, fontStyle);
this._fonts[fontRef] = newFont;
fonts[familyName] = newFont;
var entry = this._fonts.Values.FirstOrDefault(f => f.font == font);
if (entry != null) {
entry.onTextureRebuilt();
foreach (var fontInfos in this._fonts) {
if (fontInfos != null) {
foreach (var f in fontInfos.Values) {
if (f.font == font) {
f.onTextureRebuilt();
}
}
}
class GlyphInfo {
public static GlyphInfo empty = new GlyphInfo(Rect.zero,0, 0, new Vector2(0, 0),
new Vector2(0, 0), new Vector2(0, 0), new Vector2(0, 0));
public readonly Rect rect;
public readonly float advance;
public readonly float glyphHeight;
public readonly Vector2 uvTopLeft;
public readonly Vector2 uvTopRight;
public readonly Vector2 uvBottomLeft;
public readonly Vector2 uvBottomRight;
public GlyphInfo(CharacterInfo info) {
this.rect = Rect.fromLTRB(info.minX, -info.maxY, info.maxX, -info.minY);
this.advance = info.advance;
this.glyphHeight = info.glyphHeight;
this.uvTopLeft = info.uvTopLeft;
this.uvTopRight = info.uvTopRight;
this.uvBottomLeft = info.uvBottomLeft;
this.uvBottomRight = info.uvBottomRight;
}
public GlyphInfo(Rect rect, float advance, float glyphHeight,
Vector2 uvTopLeft, Vector2 uvTopRight, Vector2 uvBottomLeft, Vector2 uvBottomRight) {
this.rect = rect;
this.advance = advance;
this.glyphHeight = glyphHeight;
this.uvTopLeft = uvTopLeft;
this.uvTopRight = uvTopRight;
this.uvBottomLeft = uvBottomLeft;
this.uvBottomRight = uvBottomRight;
}
}
internal static GlyphInfo getGlyphInfo(this Font font, char ch, int fontSize, UnityEngine.FontStyle fontStyle) {
internal static bool getGlyphInfo(this Font font, char ch, out CharacterInfo info, int fontSize,
UnityEngine.FontStyle fontStyle) {
return GlyphInfo.empty;
info = default;
return false;
CharacterInfo info;
Debug.LogWarning($"character info not found from the given font: character '{ch}' (code{(int)ch}) font: ${font.name}");
Debug.LogWarning(
$"character info not found from the given font: character '{ch}' (code{(int) ch}) font: ${font.name}");
return GlyphInfo.empty;
info = default;
return false;
return new GlyphInfo(info);
return true;
internal static void RequestCharactersInTextureSafe(this Font font, string text, int fontSize,
UnityEngine.FontStyle fontStyle = UnityEngine.FontStyle.Normal) {
if (fontSize <= 0) {

12
Runtime/ui/painting/txt/mesh_generator.cs


if (fontSizeToLoad == 0) {
continue;
}
var glyphInfo = font.getGlyphInfo(ch, fontSizeToLoad, style.UnityFontStyle);
var minX = glyphInfo.rect.left / this.scale;
var maxX = glyphInfo.rect.right / this.scale;
var minY = glyphInfo.rect.top / this.scale;
var maxY = glyphInfo.rect.bottom / this.scale;
font.getGlyphInfo(ch, out var glyphInfo, fontSizeToLoad, style.UnityFontStyle);
var minX = glyphInfo.minX / this.scale;
var maxX = glyphInfo.maxX / this.scale;
var minY = -glyphInfo.maxY / this.scale;
var maxY = -glyphInfo.minY / this.scale;
var baseIndex = vertices.Count;

2
Runtime/ui/text.cs


internal UnityEngine.FontStyle UnityFontStyle {
get {
bool isBold = this.fontWeight == FontWeight.bold;
bool isBold = this.fontWeight.index == FontWeight.bold.index;
if (this.fontStyle == FontStyle.italic) {
if (isBold) {
return UnityEngine.FontStyle.BoldAndItalic;

58
Runtime/ui/txt/layout.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {

List<float> _advances = new List<float>();
List<float> _positions = new List<float>();
float _advance;
Rect _bounds;
UnityEngine.Rect _bounds;
TabStops _tabStops;

public void doLayout(float offset, TextBuff buff, int start, int count, TextStyle style) {
this._start = start;
this._count = count;
this._advances.resize(count, 0);
this._positions.resize(count, 0);
this._advances.reset(count);
this._positions.reset(count);
this._bounds = null;
this._bounds = default;
var font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
font.RequestCharactersInTextureSafe(buff.text, style.UnityFontSize, style.UnityFontStyle);
int wordstart = start == buff.size
? start
: LayoutUtils.getPrevWordBreakForCache(buff, start + 1);

int wordCount = Math.Min(start + count, wordend) - iter;
int wordCount = Mathf.Min(start + count, wordend) - iter;
iter - wordstart, wordCount, style);
iter - wordstart, wordCount, style, font);
TextBuff buff, int start, int wordCount, TextStyle style) {
TextBuff buff, int start, int wordCount, TextStyle style, Font font) {
var font = FontManager.instance.getOrCreate(style.fontFamily, style.fontWeight, style.fontStyle).font;
font.RequestCharactersInTextureSafe(buff.subBuff(start, wordCount).getString(),
style.UnityFontSize,
style.UnityFontStyle);
float x = this._advance;
float letterSpace = style.letterSpacing;
float letterSpaceHalfLeft = letterSpace * 0.5f;

x += letterSpace;
}
var glyphInfo = font.getGlyphInfo(ch, style.UnityFontSize, style.UnityFontStyle);
var rect = glyphInfo.rect;
rect = rect.translate(x, 0);
if (this._bounds == null || this._bounds.isEmpty) {
this._bounds = rect;
}
else {
this._bounds = this._bounds.expandToInclude(rect);
if (font.getGlyphInfo(ch, out var glyphInfo, style.UnityFontSize, style.UnityFontStyle)) {
var minX = glyphInfo.minX + x;
var maxX = glyphInfo.maxX + x;
var minY = -glyphInfo.maxY;
var maxY = -glyphInfo.minY;
if (this._bounds.width <= 0 || this._bounds.height <= 0) {
this._bounds = UnityEngine.Rect.MinMaxRect(
minX, minY, maxX, maxY);
} else {
if (minX < this._bounds.x) {
this._bounds.x = minX;
}
if (minY < this._bounds.y) {
this._bounds.y = minY;
}
if (maxX > this._bounds.xMax) {
this._bounds.xMax = maxX;
}
if (maxY > this._bounds.yMax) {
this._bounds.yMax = maxY;
}
}
this._positions[i + layoutOffset] = x;
float advance = glyphInfo.advance;
if (ch == '\t') {

}
public Rect getBounds() {
return this._bounds;
return Rect.fromLTWH(this._bounds.x, this._bounds.y, this._bounds.width, this._bounds.height);
}
}
}

15
Runtime/ui/txt/linebreaker.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using Unity.UIWidgets.InternalBridge;
using UnityEngine;
namespace Unity.UIWidgets.ui {

}
if (this._tabWidth == int.MaxValue) {
this._font.RequestCharactersInTextureSafe(" ", this._fontSize);
var glyphInfo = this._font.getGlyphInfo(' ', this._fontSize, UnityEngine.FontStyle.Normal);
this._tabWidth = (int)Math.Round(glyphInfo.advance * kTabSpaceCount);
this._font.RequestCharactersInTextureSafe(" ", this._fontSize);
this._font.getGlyphInfo(' ', out var glyphInfo, this._fontSize, UnityEngine.FontStyle.Normal);
this._tabWidth = glyphInfo.advance * kTabSpaceCount;
}
}

public void resize(int size) {
if (this._charWidths.Count < size) {
this._charWidths.AddRange(Enumerable.Repeat(0.0f, size - this._charWidths.Count));
NoAllocHelpersBridge<float>.ResizeList(this._charWidths, size);
}
}

this._candidates.Clear();
this._widths.Clear();
this._breaks.Clear();
this._textBuf = null;
this._textBuf = default;
}
public List<float> getWidths() {

4
Runtime/ui/txt/paint_record.cs


namespace Unity.UIWidgets.ui {
class PaintRecord {
public PaintRecord(TextStyle style, Offset offset, TextBlob _text,
public PaintRecord(TextStyle style, Offset offset, TextBlob text,
this._text = _text;
this._text = text;
this._line = line;
this._runWidth = runWidth;
this._metrics = metrics;

7
Runtime/ui/txt/paragraph.cs


var ascent = -font.ascent * fontSize / font.fontSize;
var descent = (font.lineHeight - font.ascent) * fontSize / font.fontSize;
font.RequestCharactersInTextureSafe("x", fontSize, UnityEngine.FontStyle.Normal);
var glyphInfo = font.getGlyphInfo('x', fontSize, UnityEngine.FontStyle.Normal);
font.getGlyphInfo('x', out var glyphInfo, fontSize, UnityEngine.FontStyle.Normal);
float fxHeight = glyphInfo.glyphHeight;
return new FontMetrics(ascent, descent, fxHeight: fxHeight);

public readonly int endIncludingNewLine;
public readonly bool hardBreak;
}
const int TabSpaceCount = 4;
bool _needsLayout = true;

lineBreaker.finish();
}
return;
}
List<Range<int>> findWords(int start, int end) {

4
Runtime/ui/txt/text_buff.cs


using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.ui {
class TextBuff {
struct TextBuff {
public readonly string text;
public readonly int offset;
public readonly int size;

return new TextBuff(this.text, this.offset + shift, size);
}
public String getString() {
public override string ToString() {
return this.text.Substring(this.offset, this.size);
}
}

2
Runtime/ui/txt/wordbreaker.cs


}
public void finish() {
this._text = null;
this._text = default;
}
int _findNextBreakInEmailOrUrl() {

6
Runtime/ui/window.cs


public static Window instance {
get {
D.assert(_instance != null,
"Window.instance is null. " +
() => "Window.instance is null. " +
"This usually happens when there is a callback from outside of UIWidgets. " +
"Try to use \"using (WindowProvider.of(BuildContext).getScope()) { ... }\" to wrap your code.");
return _instance;

if (value == null) {
D.assert(_instance != null, "Window.instance is already cleared.");
D.assert(_instance != null, () => "Window.instance is already cleared.");
D.assert(_instance == null, "Window.instance is already assigned.");
D.assert(_instance == null, () => "Window.instance is already assigned.");
_instance = value;
}
}

10
Runtime/widgets/app.cs


D.assert(
home == null ||
!this.routes.ContainsKey(Navigator.defaultRouteName),
"If the home property is specified, the routes table " +
() => "If the home property is specified, the routes table " +
"cannot include an entry for \" / \", since it would be redundant."
);

this.routes.ContainsKey(Navigator.defaultRouteName) ||
onGenerateRoute != null ||
onUnknownRoute != null,
"Either the home property must be specified, " +
() => "Either the home property must be specified, " +
"or the routes table must include an entry for \"/\", " +
"or there must be on onGenerateRoute callback specified, " +
"or there must be an onUnknownRoute callback specified, " +

builder != null ||
onGenerateRoute != null ||
pageRouteBuilder != null,
"If neither builder nor onGenerateRoute are provided, the " +
() => "If neither builder nor onGenerateRoute are provided, the " +
"pageRouteBuilder must be specified so that the default handler " +
"will know what kind of PageRoute transition to build."
);

if (pageContentBuilder != null) {
D.assert(this.widget.pageRouteBuilder != null,
"The default onGenerateRoute handler for WidgetsApp must have a " +
() => "The default onGenerateRoute handler for WidgetsApp must have a " +
"pageRouteBuilder set if the home or routes properties are set.");
var route = this.widget.pageRouteBuilder(
settings,

"The pageRouteBuilder for WidgetsApp must return a valid non-null Route.");
() => "The pageRouteBuilder for WidgetsApp must return a valid non-null Route.");
return route;
}

5
Runtime/widgets/automatic_keep_alive.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.scheduler;

public Ticker createTicker(TickerCallback onTick) {
this._tickers = this._tickers ?? new HashSet<Ticker>();
var debugLabel = "";
Func<string> debugLabel = null;
debugLabel = "created by " + this;
debugLabel = () => "created by " + this;
return true;
});
var result = new _AutomaticWidgetTicker<T>(onTick, this, debugLabel: debugLabel);

34
Runtime/widgets/basic.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.Runtime.rendering;
using Unity.UIWidgets.utils;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Rect = Unity.UIWidgets.ui.Rect;

public readonly float? stepHeight;
float? _stepWidth {
get {
return this.stepWidth == 0.0f ? null : this.stepWidth;
}
get { return this.stepWidth == 0.0f ? null : this.stepWidth; }
get {
return this.stepHeight == 0.0f ? null : this.stepHeight;
}
get { return this.stepHeight == 0.0f ? null : this.stepHeight; }
}
public override RenderObject createRenderObject(BuildContext context) {

properties.add(new FloatProperty("elevation", this.elevation));
properties.add(new DiagnosticsProperty<Color>("color", this.color));
properties.add(new DiagnosticsProperty<Color>("shadowColor", this.shadowColor));
}
}
public class RotatedBox : SingleChildRenderObjectWidget {
public RotatedBox(
Key key = null,
int? quarterTurns = null,
Widget child = null
) : base(key: key, child: child) {
D.assert(quarterTurns != null);
this.quarterTurns = quarterTurns;
}
public readonly int? quarterTurns;
public override RenderObject createRenderObject(BuildContext context) {
return new RenderRotatedBox(this.quarterTurns ?? 0);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
(renderObject as RenderRotatedBox).quarterTurns = this.quarterTurns ?? 0;
}
}

3
Runtime/widgets/binding.cs


protected override void handlePlatformBrightnessChanged() {
base.handlePlatformBrightnessChanged();
foreach (WidgetsBindingObserver observer in this._observers)
foreach (WidgetsBindingObserver observer in this._observers) {
}
}
protected virtual void handleLocaleChanged() {

2
Runtime/widgets/container.cs


D.assert(decoration == null || decoration.debugAssertIsValid());
D.assert(constraints == null || constraints.debugAssertIsValid());
D.assert(color == null || decoration == null,
"Cannot provide both a color and a decoration\n" +
() => "Cannot provide both a color and a decoration\n" +
"The color argument is just a shorthand for \"decoration: new BoxDecoration(color: color)\"."
);

2
Runtime/widgets/dismissible.cs


internal _AutomaticWidgetTicker(
TickerCallback onTick,
AutomaticKeepAliveClientWithTickerProviderStateMixin<T> creator,
string debugLabel = null) :
Func<string> debugLabel = null) :
base(onTick: onTick, debugLabel: debugLabel) {
this._creator = creator;
}

11
Runtime/widgets/drag_target.cs


using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.utils;
namespace Unity.UIWidgets.widgets {
public delegate bool DragTargetWillAccept<T>(T data);

public enum DragAnchor {
child,
pointer
}
static class _DragUtils {
public static List<T> _mapAvatarsToData<T>(List<_DragAvatar<T>> avatars) {
return avatars.Select(avatar => avatar.data).ToList();
}
}
public class Draggable<T> : StatefulWidget {

return new MetaData(
metaData: this,
behavior: HitTestBehavior.translucent,
child: this.widget.builder(context, DragUtils._mapAvatarsToData(this._candidateAvatars),
DragUtils._mapAvatarsToData(this._rejectedAvatars)));
child: this.widget.builder(context, _DragUtils._mapAvatarsToData(this._candidateAvatars),
_DragUtils._mapAvatarsToData(this._rejectedAvatars)));
}
}

23
Runtime/widgets/editable_text.cs


}
void _onFloatingCursorResetTick() {
Offset finalPosition = this.renderEditable.getLocalRectForCaret(this._lastTextPosition).centerLeft - this._floatingCursorOffset;
Offset finalPosition = this.renderEditable.getLocalRectForCaret(this._lastTextPosition).centerLeft -
this._floatingCursorOffset;
this.renderEditable.setFloatingCursor(FloatingCursorDragState.End, finalPosition, this._lastTextPosition);
if (this._lastTextPosition.offset != this.renderEditable.selection.baseOffset)
this._handleSelectionChanged(TextSelection.collapsed(offset: this._lastTextPosition.offset), this.renderEditable, SelectionChangedCause.forcePress);
this.renderEditable.setFloatingCursor(FloatingCursorDragState.End, finalPosition,
this._lastTextPosition);
if (this._lastTextPosition.offset != this.renderEditable.selection.baseOffset) {
this._handleSelectionChanged(TextSelection.collapsed(offset: this._lastTextPosition.offset),
this.renderEditable, SelectionChangedCause.forcePress);
}
this._startCaretRect = null;
this._lastTextPosition = null;
this._pointOffsetOrigin = null;

float lerpX = MathUtils.lerpFloat(this._lastBoundedOffset.dx, finalPosition.dx, lerpValue);
float lerpY = MathUtils.lerpFloat(this._lastBoundedOffset.dy, finalPosition.dy, lerpValue);
this.renderEditable.setFloatingCursor(FloatingCursorDragState.Update, new Offset(lerpX, lerpY), this._lastTextPosition, resetLerpValue: lerpValue);
this.renderEditable.setFloatingCursor(FloatingCursorDragState.Update, new Offset(lerpX, lerpY),
this._lastTextPosition, resetLerpValue: lerpValue);
}
}

public void requestKeyboard() {
if (this._hasFocus) {
this._openInputConnection();
}
else {
} else {
for (int i = ancestorScopes.Count - 1; i >= 1; i -= 1)
for (int i = ancestorScopes.Count - 1; i >= 1; i -= 1) {
}
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;
}
}

34
Runtime/widgets/form.cs


public class FormState : State<Form> {
int _generation = 0;
public readonly HashSet<FormFieldState<dynamic>> _fields = new HashSet<FormFieldState<dynamic>>();
readonly HashSet<FormFieldState> _fields = new HashSet<FormFieldState>();
public FormState() {
}

this.setState(() => { ++this._generation; });
}
public void _register(FormFieldState<dynamic> field) {
public void _register(FormFieldState field) {
public void _unregister(FormFieldState<dynamic> field) {
public void _unregister(FormFieldState field) {
this._fields.Remove(field);
}

);
}
void save() {
foreach (FormFieldState<dynamic> field in this._fields) {
public void save() {
foreach (FormFieldState field in this._fields) {
void reset() {
foreach (FormFieldState<dynamic> field in this._fields) {
public void reset() {
foreach (FormFieldState field in this._fields) {
field.reset();
}

bool validate() {
public bool validate() {
this._forceRebuild();
return this._validate();
}

foreach (FormFieldState<dynamic> field in this._fields) {
foreach (FormFieldState field in this._fields) {
hasError = !field.validate() || hasError;
}

}
}
public class FormFieldState<T> : State<FormField<T>> where T : class {
public interface FormFieldState {
void save();
bool validate();
void reset();
}
public class FormFieldState<T> : State<FormField<T>>, FormFieldState where T : class {
T _value;
string _errorText;

}
}
public void reset() {
public virtual void reset() {
this.setState(() => {
this._value = this.widget.initialValue;
this._errorText = null;

}
public override void deactivate() {
Form.of(this.context)?._unregister(this as FormFieldState<dynamic>);
Form.of(this.context)?._unregister(this);
base.deactivate();
}

}
Form.of(context)?._register(this as FormFieldState<dynamic>);
Form.of(context)?._register(this);
return this.widget.builder(this);
}
}

4
Runtime/widgets/framework.cs


public override void deactivate() {
base.deactivate();
D.assert(!this.renderObject.attached,
"A RenderObject was still attached when attempting to deactivate its " +
() => "A RenderObject was still attached when attempting to deactivate its " +
"RenderObjectElement: " + this.renderObject);
}

"A RenderObject was still attached when attempting to unmount its " +
() => "A RenderObject was still attached when attempting to unmount its " +
"RenderObjectElement: " + this.renderObject);
this.widget.didUnmountRenderObject(this.renderObject);
}

84
Runtime/widgets/gesture_detector.cs


internal override bool _debugAssertTypeMatches(Type type) {
D.assert(type == typeof(T),
"GestureRecognizerFactory of type " + typeof(T) + " was used where type $type was specified.");
() => "GestureRecognizerFactory of type " + typeof(T) + " was used where type $type was specified.");
return true;
}
}

GestureDragUpdateCallback onPanUpdate = null,
GestureDragEndCallback onPanEnd = null,
GestureDragCancelCallback onPanCancel = null,
GestureScaleStartCallback onScaleStart = null,
GestureScaleUpdateCallback onScaleUpdate = null,
GestureScaleEndCallback onScaleEnd = null,
HitTestBehavior behavior = HitTestBehavior.deferToChild,
DragStartBehavior dragStartBehavior = DragStartBehavior.down
) : base(key) {

onHorizontalDragStart != null || onHorizontalDragUpdate != null ||
onHorizontalDragEnd != null;
bool haveLongPress = onLongPress != null || onLongPressUp != null;
bool haveLongPressDrag = onLongPressDragStart != null || onLongPressDragUpdate != null || onLongPressDragUp != null;
bool haveLongPressDrag = onLongPressDragStart != null || onLongPressDragUpdate != null ||
onLongPressDragUp != null;
if (havePan) {
bool haveScale = onScaleStart != null || onScaleUpdate != null || onScaleEnd != null;
if (havePan || haveScale) {
if (havePan && haveScale) {
throw new UIWidgetsError(
"Incorrect GestureDetector arguments.\n" +
"Having both a pan gesture recognizer and a scale gesture recognizer is redundant; scale is a superset of pan. Just use the scale gesture recognizer."
);
}
string recognizer = havePan ? "pan" : "scale";
"Simultaneously having a vertical drag gesture recognizer, a horizontal drag gesture recognizer, and a pan gesture recognizer " +
"will result in the pan gesture recognizer being ignored, since the other two will catch all drags."
$"Simultaneously having a vertical drag gesture recognizer, a horizontal drag gesture recognizer, and a {recognizer} gesture recognizer " +
$"will result in the {recognizer} gesture recognizer being ignored, since the other two will catch all drags."
"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."
);
"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.onPanUpdate = onPanUpdate;
this.onPanEnd = onPanEnd;
this.onPanCancel = onPanCancel;
this.onScaleStart = onScaleStart;
this.onScaleUpdate = onScaleUpdate;
this.onScaleEnd = onScaleEnd;
this.behavior = behavior;
this.dragStartBehavior = dragStartBehavior;
}

public readonly GestureDragUpdateCallback onPanUpdate;
public readonly GestureDragEndCallback onPanEnd;
public readonly GestureDragCancelCallback onPanCancel;
public readonly GestureScaleStartCallback onScaleStart;
public readonly GestureScaleUpdateCallback onScaleUpdate;
public readonly GestureScaleEndCallback onScaleEnd;
public readonly HitTestBehavior behavior;
public readonly DragStartBehavior dragStartBehavior;

instance => { instance.onLongPress = this.onLongPress; }
);
}
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;
}
);
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;
}
);
}
if (this.onVerticalDragDown != null ||

instance.onEnd = this.onPanEnd;
instance.onCancel = this.onPanCancel;
instance.dragStartBehavior = this.dragStartBehavior;
}
);
}
if (this.onScaleStart != null ||
this.onScaleUpdate != null ||
this.onScaleEnd != null) {
gestures[typeof(ScaleGestureRecognizer)] =
new GestureRecognizerFactoryWithHandlers<ScaleGestureRecognizer>(
() => new ScaleGestureRecognizer(debugOwner: this),
instance => {
instance.onStart = this.onScaleStart;
instance.onUpdate = this.onScaleUpdate;
instance.onEnd = this.onScaleEnd;
}
);
}

? oldRecognizers[type]
: gestures[type].constructorRaw();
D.assert(this._recognizers[type].GetType() == type,
"GestureRecognizerFactory of type " + type + " created a GestureRecognizer of type " +
this._recognizers[type].GetType() +
". The GestureRecognizerFactory must be specialized with the type of the class that it returns from its constructor method.");
() => "GestureRecognizerFactory of type " + type + " created a GestureRecognizer of type " +
this._recognizers[type].GetType() +
". The GestureRecognizerFactory must be specialized with the type of the class that it returns from its constructor method.");
gestures[type].initializerRaw(this._recognizers[type]);
}

12
Runtime/widgets/implicit_animations.cs


D.assert(decoration == null || decoration.debugAssertIsValid());
D.assert(constraints == null || constraints.debugAssertIsValid());
D.assert(color == null || decoration == null,
"Cannot provide both a color and a decoration\n" +
() => "Cannot provide both a color and a decoration\n" +
"The color argument is just a shorthand for \"decoration: new BoxDecoration(backgroundColor: color)\".");
this.alignment = alignment;
this.padding = padding;

}
class _AnimatedOpacityState : ImplicitlyAnimatedWidgetState<AnimatedOpacity> {
FloatTween _opacity;
NullableFloatTween _opacity;
this._opacity = (FloatTween) visitor.visit(this, this._opacity, this.widget.opacity,
(float value) => new FloatTween(begin: value, end: 1.0f));
this._opacity = (NullableFloatTween) visitor.visit(this, this._opacity, this.widget.opacity,
(float? value) => new NullableFloatTween(begin: value));
this._opacityAnimation = this.animation.drive(this._opacity);
float? endValue = this._opacity.end ?? this._opacity.begin ?? null;
D.assert(endValue != null);
this._opacityAnimation = this.animation.drive(new FloatTween(begin: this._opacity.begin.Value, end: endValue.Value));
}
public override Widget build(BuildContext context) {

4
Runtime/widgets/localizations.cs


return null;
}
D.assert((bool) (scope != null), "a Localizations ancestor was not found");
D.assert((bool) (scope != null), () => "a Localizations ancestor was not found");
return scope.localizationsState.locale;
}

(_LocalizationsScope) context.inheritFromWidgetOfExactType(typeof(_LocalizationsScope));
D.assert(scope != null, "a Localizations ancestor was not found");
D.assert(scope != null, () => "a Localizations ancestor was not found");
return new List<LocalizationsDelegate>(scope.localizationsState.widget.delegates);
}

4
Runtime/widgets/page_view.cs


public float page {
get {
D.assert(this.positions.isNotEmpty(),
"PageController.page cannot be accessed before a PageView is built with it."
() => "PageController.page cannot be accessed before a PageView is built with it."
"The page property cannot be read when multiple PageViews are attached to " +
() => "The page property cannot be read when multiple PageViews are attached to " +
"the same PageController."
);
_PagePosition position = (_PagePosition) this.position;

36
Runtime/widgets/routes.cs


public virtual AnimationController createAnimationController() {
D.assert(this._transitionCompleter.CurState == PromiseState.Pending,
$"Cannot reuse a {this.GetType()} after disposing it.");
() => $"Cannot reuse a {this.GetType()} after disposing it.");
TimeSpan duration = this.transitionDuration;
D.assert(duration >= TimeSpan.Zero);
return new AnimationController(

public virtual Animation<float> createAnimation() {
D.assert(this._transitionCompleter.CurState == PromiseState.Pending,
$"Cannot reuse a {this.GetType()} after disposing it.");
() => $"Cannot reuse a {this.GetType()} after disposing it.");
D.assert(this._controller != null);
return this._controller.view;
}

readonly ProxyAnimation _secondaryAnimation = new ProxyAnimation(Animations.kAlwaysDismissedAnimation);
protected internal override void install(OverlayEntry insertionPoint) {
D.assert(!this._transitionCompleter.isCompleted, $"Cannot install a {this.GetType()} after disposing it.");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot install a {this.GetType()} after disposing it.");
D.assert(this._controller != null, $"{this.GetType()}.createAnimationController() returned null.");
D.assert(this._controller != null, () => $"{this.GetType()}.createAnimationController() returned null.");
D.assert(this._animation != null, $"{this.GetType()}.createAnimation() returned null.");
D.assert(this._animation != null, () => $"{this.GetType()}.createAnimation() returned null.");
$"{this.GetType()}.didPush called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it.");
() => $"{this.GetType()}.didPush called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot reuse a {this.GetType()} after disposing it.");
this._animation.addStatusListener(this._handleStatusChanged);
return this._controller.forward();
}

$"{this.GetType()}.didReplace called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it.");
() => $"{this.GetType()}.didReplace called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot reuse a {this.GetType()} after disposing it.");
if (oldRoute is TransitionRoute route) {
this._controller.setValue(route._controller.value);
}

protected internal override bool didPop(object result) {
D.assert(this._controller != null,
$"{this.GetType()}.didPop called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it.");
() => $"{this.GetType()}.didPop called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot reuse a {this.GetType()} after disposing it.");
this._result = result;
this._controller.reverse();
return base.didPop(result);

D.assert(this._controller != null,
$"{this.GetType()}.didPopNext called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it.");
() => $"{this.GetType()}.didPopNext called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot reuse a {this.GetType()} after disposing it.");
this._updateSecondaryAnimation(nextRoute);
base.didPopNext(nextRoute);
}

$"{this.GetType()}.didChangeNext called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, $"Cannot reuse a {this.GetType()} after disposing it.");
() => $"{this.GetType()}.didChangeNext called before calling install() or after calling dispose().");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot reuse a {this.GetType()} after disposing it.");
this._updateSecondaryAnimation(nextRoute);
base.didChangeNext(nextRoute);
}

}
protected internal override void dispose() {
D.assert(!this._transitionCompleter.isCompleted, $"Cannot dispose a {this.GetType()} twice.");
D.assert(!this._transitionCompleter.isCompleted, () => $"Cannot dispose a {this.GetType()} twice.");
this._controller?.dispose();
this._transitionCompleter.Resolve(this._result);
base.dispose();

public void addScopedWillPopCallback(WillPopCallback callback) {
D.assert(this._scopeKey.currentState != null,
"Tried to add a willPop callback to a route that is not currently in the tree.");
() => "Tried to add a willPop callback to a route that is not currently in the tree.");
"Tried to remove a willPop callback from a route that is not currently in the tree.");
() => "Tried to remove a willPop callback from a route that is not currently in the tree.");
this._willPopCallbacks.Remove(callback);
}

2
Runtime/widgets/scroll_activity.cs


D.assert(details != null);
D.assert(
motionStartDistanceThreshold == null || motionStartDistanceThreshold > 0.0,
"motionStartDistanceThreshold must be a positive number or null"
() => "motionStartDistanceThreshold must be a positive number or null"
);
this._del = del;

8
Runtime/widgets/scroll_controller.cs


public ScrollPosition position {
get {
D.assert(this._positions.isNotEmpty(), "ScrollController not attached to any scroll views.");
D.assert(this._positions.Count == 1, "ScrollController attached to multiple scroll views.");
D.assert(this._positions.isNotEmpty(), () => "ScrollController not attached to any scroll views.");
D.assert(this._positions.Count == 1, () => "ScrollController attached to multiple scroll views.");
return this._positions.Single();
}
}

TimeSpan duration,
Curve curve
) {
D.assert(this._positions.isNotEmpty(), "ScrollController not attached to any scroll views.");
D.assert(this._positions.isNotEmpty(), () => "ScrollController not attached to any scroll views.");
List<IPromise> animations = Enumerable.Repeat((IPromise) null, this._positions.Count).ToList();
for (int i = 0; i < this._positions.Count; i += 1) {
animations[i] = this._positions[i].animateTo(to, duration: duration, curve: curve);

}
public void jumpTo(float value) {
D.assert(this._positions.isNotEmpty(), "ScrollController not attached to any scroll views.");
D.assert(this._positions.isNotEmpty(), () => "ScrollController not attached to any scroll views.");
foreach (ScrollPosition position in new List<ScrollPosition>(this._positions)) {
position.jumpTo(value);
}

2
Runtime/widgets/scroll_position.cs


public override void correctBy(float correction) {
D.assert(
this._pixels != null,
"An initial pixels value must exist by caling correctPixels on the ScrollPosition"
() => "An initial pixels value must exist by caling correctPixels on the ScrollPosition"
);
this._pixels += correction;

2
Runtime/widgets/scroll_view.cs


DragStartBehavior dragStartBehavior = DragStartBehavior.down
) : base(key: key) {
D.assert(!(controller != null && primary == true),
"Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +
() => "Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +
"You cannot both set primary to true and pass an explicit controller.");
D.assert(!shrinkWrap || center == null);
D.assert(anchor >= 0.0f && anchor <= 1.0f);

3
Runtime/widgets/single_child_scroll_view.cs


using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.utils;
using UnityEngine;
using Rect = Unity.UIWidgets.ui.Rect;

DragStartBehavior dragStartBehavior = DragStartBehavior.down
) : base(key: key) {
D.assert(!(controller != null && primary == true),
"Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +
() => "Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. " +
"You cannot both set primary to true and pass an explicit controller.");
this.scrollDirection = scrollDirection;
this.reverse = reverse;

11
Runtime/widgets/ticker_provider.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.scheduler;

);
});
var debugLabel = "";
Func<string> debugLabel = null;
debugLabel = "created by " + this;
debugLabel = () => "created by " + this;
return true;
});
this._ticker = new Ticker(onTick, debugLabel: debugLabel);

public Ticker createTicker(TickerCallback onTick) {
this._tickers = this._tickers ?? new HashSet<Ticker>();
var debugLabel = "";
Func<string> debugLabel = null;
debugLabel = "created by " + this;
debugLabel = () => "created by " + this;
return true;
});
var result = new _WidgetTicker<T>(onTick, this, debugLabel: debugLabel);

internal _WidgetTicker(
TickerCallback onTick,
TickerProviderStateMixin<T> creator,
string debugLabel = null) :
Func<string> debugLabel = null) :
base(onTick: onTick, debugLabel: debugLabel) {
this._creator = creator;
}

6
Runtime/widgets/visibility.cs


) : base(key: key) {
D.assert(child != null);
D.assert(maintainState == true || maintainAnimation == false,
"Cannot maintain animations if the state is not also maintained.");
() => "Cannot maintain animations if the state is not also maintained.");
"Cannot maintain size if animations are not maintained.");
() => "Cannot maintain size if animations are not maintained.");
"Cannot maintain interactivity if size is not maintained.");
() => "Cannot maintain interactivity if size is not maintained.");
this.replacement = replacement ?? SizedBox.shrink();
this.child = child;
this.visible = visible;

80
Samples/UIWidgetSample/MaterialSample.cs


namespace UIWidgetsSample {
public class MaterialSample : UIWidgetsSamplePanel {
const int testCaseId = 7;
const int testCaseId = 6;
readonly List<Widget> testCases = new List<Widget> {
new MaterialButtonWidget(),

public class BottomAppBarWidget : StatelessWidget {
public BottomAppBarWidget(Key key = null) : base(key) {
}
public override Widget build(BuildContext context) {

mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: new List<Widget> {
new IconButton(icon: new Icon(Unity.UIWidgets.material.Icons.menu), onPressed: () => { }),
new IconButton(icon: new Icon(Unity.UIWidgets.material.Icons.account_balance), onPressed: () => { })
new IconButton(icon: new Icon(Unity.UIWidgets.material.Icons.account_balance),
onPressed: () => { })
})));
}
}

}
}
public class MaterialButtonWidget : StatefulWidget {
public class MaterialButtonWidget : StatefulWidget {
public MaterialButtonWidget(Key key = null) : base(key) {
}

public class MaterialSliderState : State<MaterialSliderWidget> {
float _value = 0.0f;
float _value = 0.8f;
children : new List<Widget> {
new Container(
children: new List<Widget> {
new Padding(
padding: EdgeInsets.only(top: 100.0f),
child: new Container(
divisions: 10,
min: 0.4f,
label: "Here",
)
)
)
internal class MaterialNavigationBarWidget : StatefulWidget
{
public MaterialNavigationBarWidget(Key key = null) : base(key)
{
class MaterialNavigationBarWidget : StatefulWidget {
public MaterialNavigationBarWidget(Key key = null) : base(key) {
public override State createState()
{
public override State createState() {
internal class MaterialNavigationBarWidgetState : SingleTickerProviderStateMixin<MaterialNavigationBarWidget> {
class MaterialNavigationBarWidgetState : SingleTickerProviderStateMixin<MaterialNavigationBarWidget> {
public MaterialNavigationBarWidgetState()
{
public MaterialNavigationBarWidgetState() {
public override Widget build(BuildContext context)
{
public override Widget build(BuildContext context) {
return new Scaffold(
bottomNavigationBar: new Container(
height: 100,

type: BottomNavigationBarType.shifting,
// type: BottomNavigationBarType.fix,
items: new List<BottomNavigationBarItem>
{
items: new List<BottomNavigationBarItem> {
new BottomNavigationBarItem(
icon: new Icon(icon: Unity.UIWidgets.material.Icons.work, size: 30),
title: new Text("Work"),

);
}
}
internal class MaterialReorderableListViewWidget : StatefulWidget
{
public MaterialReorderableListViewWidget(Key key = null) : base(key)
{
class MaterialReorderableListViewWidget : StatefulWidget {
public MaterialReorderableListViewWidget(Key key = null) : base(key) {
public override State createState()
{
public override State createState() {
internal class MaterialReorderableListViewWidgetState : State<MaterialReorderableListViewWidget>
{
private List<string> items = new List<string> {"First", "Second", "Third"};
class MaterialReorderableListViewWidgetState : State<MaterialReorderableListViewWidget> {
List<string> items = new List<string> {"First", "Second", "Third"};
public override Widget build(BuildContext context)
{
public override Widget build(BuildContext context) {
children: new List<Widget>
{
children: new List<Widget> {
new Scaffold(
body: new Scrollbar(
child: new ReorderableListView(

)
);
}).ToList(),
onReorder: (int oldIndex, int newIndex) =>
{
this.setState(() =>
{
if (newIndex > oldIndex) newIndex -= 1;
onReorder: (int oldIndex, int newIndex) => {
this.setState(() => {
if (newIndex > oldIndex) {
newIndex -= 1;
}
string item = this.items[oldIndex];
this.items.RemoveAt(oldIndex);
this.items.Insert(newIndex, item);

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存