using System; using Unity.UIWidgets.foundation; using Unity.UIWidgets.painting; using Unity.UIWidgets.ui; using UnityEngine; using Canvas = Unity.UIWidgets.ui.Canvas; using Color = Unity.UIWidgets.ui.Color; using Rect = Unity.UIWidgets.ui.Rect; using TextStyle = Unity.UIWidgets.painting.TextStyle; namespace Unity.UIWidgets.widgets { class BannerConstants { public const float _kOffset = 40.0f; public const float _kHeight = 12.0f; public const float _kBottomOffset = _kOffset + 0.707f * _kHeight; public static readonly Rect _kRect = Rect.fromLTWH(-_kOffset, _kOffset - _kHeight, _kOffset * 2.0f, _kHeight); public static readonly Color _kColor = new Color(0xA0B71C1C); public static readonly TextStyle _kTextStyle = new TextStyle( color: new Color(0xFFFFFFFF), fontSize: _kHeight * 0.85f, fontWeight: FontWeight.w700, height: 1.0f ); } public enum BannerLocation { topStart, topEnd, bottomStart, bottomEnd, } public class BannerPainter : AbstractCustomPainter { public BannerPainter( string message, BannerLocation? location, Color color = null, TextStyle textStyle = null ) { D.assert(message != null); D.assert(location != null); this.color = color ?? BannerConstants._kColor; this.message = message; this.location = location; this.textStyle = textStyle ?? BannerConstants._kTextStyle; } public readonly string message; public readonly BannerLocation? location; public readonly Color color; public readonly TextStyle textStyle; readonly BoxShadow _shadow = new BoxShadow( color: new Color(0x7F000000), blurRadius: 6.0f ); bool _prepared = false; TextPainter _textPainter; Paint _paintShadow; Paint _paintBanner; void _prepare() { _paintShadow = _shadow.toPaint(); _paintBanner = new Paint(); _paintBanner.color = color; _textPainter = new TextPainter( text: new TextSpan(style: textStyle, text: message), textAlign: TextAlign.center ); _prepared = true; } public override void paint(Canvas canvas, Size size) { if (!_prepared) { _prepare(); } canvas.translate(_translationX(size.width), _translationY(size.height)); canvas.rotate(_rotation); canvas.drawRect(BannerConstants._kRect, _paintShadow); canvas.drawRect(BannerConstants._kRect, _paintBanner); const float width = BannerConstants._kOffset * 2.0f; _textPainter.layout(minWidth: width, maxWidth: width); _textPainter.paint(canvas, BannerConstants._kRect.topLeft + new Offset(0.0f, (BannerConstants._kRect.height - _textPainter.height) / 2.0f)); } public override bool shouldRepaint(CustomPainter _oldDelegate) { BannerPainter oldDelegate = _oldDelegate as BannerPainter; return message != oldDelegate.message || location != oldDelegate.location || color != oldDelegate.color || textStyle != oldDelegate.textStyle; } public override bool? hitTest(Offset position) { return false; } float _translationX(float width) { switch (location) { case BannerLocation.bottomEnd: return width - BannerConstants._kBottomOffset; case BannerLocation.topEnd: return width; case BannerLocation.bottomStart: return BannerConstants._kBottomOffset; case BannerLocation.topStart: return 0.0f; default: throw new Exception("Unknown location: " + location); } } float _translationY(float height) { D.assert(location != null); switch (location) { case BannerLocation.bottomStart: case BannerLocation.bottomEnd: return height - BannerConstants._kBottomOffset; case BannerLocation.topStart: case BannerLocation.topEnd: return 0.0f; default: throw new Exception("Unknown location: " + location); } } float _rotation { get { switch (location) { case BannerLocation.bottomStart: case BannerLocation.topEnd: return Mathf.PI / 4.0f; case BannerLocation.bottomEnd: case BannerLocation.topStart: return -Mathf.PI / 4.0f; default: throw new Exception("Unknown location: " + location); } } } } public class Banner : StatelessWidget { public Banner( Key key = null, Widget child = null, string message = null, BannerLocation? location = null, Color color = null, TextStyle textStyle = null ) : base(key: key) { D.assert(message != null); this.child = child; this.message = message; this.location = location; this.color = color ?? BannerConstants._kColor; this.textStyle = textStyle ?? BannerConstants._kTextStyle; } public readonly Widget child; public readonly string message; public readonly BannerLocation? location; public readonly Color color; public readonly TextStyle textStyle; public override Widget build(BuildContext context) { D.assert(WidgetsD.debugCheckHasDirectionality(context)); return new CustomPaint( foregroundPainter: new BannerPainter( message: message, location: location, color: color, textStyle: textStyle ), child: child ); } public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { base.debugFillProperties(properties); properties.add(new StringProperty("message", message, showName: false)); properties.add(new EnumProperty("location", location)); properties.add(new DiagnosticsProperty("color", color, showName: false)); textStyle?.debugFillProperties(properties); } } public class CheckedModeBanner : StatelessWidget { public CheckedModeBanner( Key key = null, Widget child = null ) : base(key: key) { D.assert(child != null); this.child = child; } public readonly Widget child; public override Widget build(BuildContext context) { Widget result = child; D.assert(() => { result = new Banner( child: result, message: "DEBUG", location: BannerLocation.topEnd ); return true; }); return result; } public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { base.debugFillProperties(properties); string message = "disabled"; D.assert(() => { message = "'DEBUG'"; return true; }); properties.add(DiagnosticsNode.message(message)); } } }