您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
374 行
11 KiB
374 行
11 KiB
using System.Collections.Generic;
|
|
using uiwidgets;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.painting;
|
|
using Unity.UIWidgets.ui;
|
|
using Unity.UIWidgets.widgets;
|
|
using UnityEngine;
|
|
using Canvas = Unity.UIWidgets.ui.Canvas;
|
|
using Color = Unity.UIWidgets.ui.Color;
|
|
|
|
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.ui
|
|
{
|
|
|
|
public class ArrowUtils{
|
|
public static Color defaultArrowColor = Colors.white;
|
|
public static float defaultArrowStrokeWidth = 2.0f;
|
|
public static float defaultDistanceToArrow = 4.0f;
|
|
|
|
public static Axis axis(ArrowType? type)
|
|
{
|
|
return (type == ArrowType.up || type == ArrowType.down)
|
|
? Axis.vertical
|
|
: Axis.horizontal;
|
|
}
|
|
}
|
|
|
|
|
|
public enum ArrowType {
|
|
up,
|
|
left,
|
|
right,
|
|
down,
|
|
}
|
|
|
|
|
|
public class ArrowWrapper : StatelessWidget {
|
|
|
|
public ArrowWrapper(
|
|
Key key = null,
|
|
Widget child = null,
|
|
ArrowType? type = null,
|
|
Color arrowColor = null,
|
|
float? arrowHeadSize = null,
|
|
float? arrowStrokeWidth = null,
|
|
float? childMarginFromArrow = null
|
|
)
|
|
{
|
|
D.assert(type != null);
|
|
D.assert(arrowHeadSize != null && arrowHeadSize > 0.0);
|
|
D.assert(arrowStrokeWidth != null && arrowHeadSize > 0.0);
|
|
D.assert(childMarginFromArrow != null && childMarginFromArrow > 0.0);
|
|
direction = ArrowUtils.axis(type);
|
|
isBidirectional = false;
|
|
startArrowType = type;
|
|
endArrowType = type;
|
|
this.child = child;
|
|
|
|
this.arrowColor = arrowColor?? ArrowUtils.defaultArrowColor;
|
|
this.arrowHeadSize = arrowHeadSize?? CommonThemeUtils.defaultIconSize;
|
|
this.arrowStrokeWidth = arrowStrokeWidth ?? ArrowUtils.defaultArrowStrokeWidth;
|
|
this.childMarginFromArrow = childMarginFromArrow ?? ArrowUtils.defaultDistanceToArrow;
|
|
|
|
}
|
|
|
|
public ArrowWrapper(
|
|
Key key = null,
|
|
Widget child = null,
|
|
Axis? direction = null,
|
|
Color arrowColor = null,
|
|
float? arrowHeadSize = null,
|
|
float? arrowStrokeWidth = null,
|
|
float? childMarginFromArrow = null
|
|
)
|
|
{
|
|
D.assert(direction != null);
|
|
D.assert(arrowColor != null);
|
|
D.assert(arrowHeadSize != null && arrowHeadSize >= 0.0);
|
|
D.assert(arrowStrokeWidth != null && arrowHeadSize >= 0.0);
|
|
D.assert(childMarginFromArrow != null && childMarginFromArrow >= 0.0);
|
|
isBidirectional = true;
|
|
startArrowType =
|
|
direction == Axis.horizontal ? ArrowType.left : ArrowType.up;
|
|
endArrowType =
|
|
direction == Axis.horizontal ? ArrowType.right : ArrowType.down;
|
|
this.child = child;
|
|
this.direction = direction;
|
|
this.arrowColor = arrowColor?? ArrowUtils.defaultArrowColor;
|
|
this.arrowHeadSize = arrowHeadSize?? CommonThemeUtils.defaultIconSize;
|
|
this.arrowStrokeWidth = arrowStrokeWidth ?? ArrowUtils.defaultArrowStrokeWidth;
|
|
this.childMarginFromArrow = childMarginFromArrow ?? ArrowUtils.defaultDistanceToArrow;
|
|
|
|
}
|
|
|
|
public readonly Color arrowColor;
|
|
public readonly float? arrowHeadSize;
|
|
public readonly float? arrowStrokeWidth;
|
|
public readonly Widget child;
|
|
public readonly float childMarginFromArrow;
|
|
|
|
public readonly Axis? direction;
|
|
public readonly bool isBidirectional;
|
|
public readonly ArrowType? startArrowType;
|
|
public readonly ArrowType? endArrowType;
|
|
|
|
public float verticalMarginFromArrow {
|
|
get
|
|
{
|
|
if (child == null || direction == Axis.horizontal) return 0.0f;
|
|
return childMarginFromArrow;
|
|
}
|
|
|
|
}
|
|
|
|
public float horizontalMarginFromArrow {
|
|
get
|
|
{
|
|
if (child == null || direction == Axis.vertical) return 0.0f;
|
|
return childMarginFromArrow;
|
|
}
|
|
|
|
}
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
|
|
List<Widget> widgets = new List<Widget>();
|
|
widgets.Add(new Expanded(
|
|
child: new Container(
|
|
margin: EdgeInsets.only(
|
|
bottom: verticalMarginFromArrow,
|
|
right: horizontalMarginFromArrow
|
|
),
|
|
child: new ArrowWidget(
|
|
color: arrowColor,
|
|
headSize: arrowHeadSize,
|
|
strokeWidth: arrowStrokeWidth,
|
|
type: startArrowType,
|
|
shouldDrawHead: isBidirectional
|
|
? true
|
|
: (startArrowType == ArrowType.left ||
|
|
startArrowType == ArrowType.up)
|
|
)
|
|
)
|
|
));
|
|
if(child!= null)widgets.Add(child);
|
|
widgets.Add(new Expanded(
|
|
child: new Container(
|
|
margin: EdgeInsets.only(
|
|
top: verticalMarginFromArrow,
|
|
left: horizontalMarginFromArrow
|
|
),
|
|
child: new ArrowWidget(
|
|
color: arrowColor,
|
|
headSize: arrowHeadSize,
|
|
strokeWidth: arrowStrokeWidth,
|
|
type: endArrowType,
|
|
shouldDrawHead: isBidirectional
|
|
? true
|
|
: (endArrowType == ArrowType.right ||
|
|
endArrowType == ArrowType.down)
|
|
)
|
|
)
|
|
));
|
|
|
|
return new Flex(
|
|
direction: direction.Value,
|
|
children: widgets
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
public class ArrowWidget : StatelessWidget {
|
|
public ArrowWidget(
|
|
Color color = null,
|
|
float? headSize = null,
|
|
Key key = null,
|
|
bool shouldDrawHead = true,
|
|
float? strokeWidth = null,
|
|
ArrowType? type = null
|
|
) : base(key: key)
|
|
{
|
|
this.headSize = headSize ?? CommonThemeUtils.defaultIconSize;
|
|
this.strokeWidth = strokeWidth ?? ArrowUtils.defaultArrowStrokeWidth;
|
|
D.assert(headSize != null && headSize > 0.0);
|
|
D.assert(strokeWidth != null && strokeWidth > 0.0);
|
|
D.assert(type != null);
|
|
this.color = color ?? ArrowUtils.defaultArrowColor;
|
|
this.shouldDrawHead = shouldDrawHead;
|
|
this.type = type;
|
|
|
|
_painter = new _ArrowPainter(
|
|
headSize: headSize,
|
|
color: color,
|
|
strokeWidth: strokeWidth,
|
|
type: type,
|
|
shouldDrawHead: shouldDrawHead
|
|
);
|
|
}
|
|
|
|
public readonly Color color;
|
|
|
|
/// The arrow head is a Equilateral triangle
|
|
public readonly float? headSize;
|
|
|
|
public readonly float? strokeWidth;
|
|
|
|
public readonly ArrowType? type;
|
|
|
|
public readonly CustomPainter _painter;
|
|
|
|
public readonly bool shouldDrawHead;
|
|
|
|
public override Widget build(BuildContext context) {
|
|
return new CustomPaint(
|
|
painter: _painter,
|
|
child: new Container()
|
|
);
|
|
}
|
|
}
|
|
|
|
public class _ArrowPainter : CustomPainter {
|
|
public _ArrowPainter(
|
|
float? headSize = null,
|
|
float? strokeWidth = null,
|
|
Color color = null,
|
|
bool shouldDrawHead = true,
|
|
ArrowType? type = null
|
|
)
|
|
{
|
|
D.assert(headSize != null);
|
|
D.assert(color != null);
|
|
D.assert(strokeWidth != null);
|
|
D.assert(type != null);
|
|
D.assert(shouldDrawHead != null);
|
|
// the height of an equilateral triangle
|
|
headHeight = 0.5f * Mathf.Sqrt(3) * headSize.Value;
|
|
this.headSize = headSize?? CommonThemeUtils.defaultIconSize;
|
|
this.strokeWidth = strokeWidth?? ArrowUtils.defaultArrowStrokeWidth;
|
|
this.color = color?? ArrowUtils.defaultArrowColor;
|
|
this.shouldDrawHead = shouldDrawHead;
|
|
this.type = type;
|
|
}
|
|
|
|
public readonly Color color;
|
|
public readonly float headSize;
|
|
public readonly bool shouldDrawHead;
|
|
public readonly float strokeWidth;
|
|
public readonly ArrowType? type;
|
|
|
|
public readonly float headHeight;
|
|
|
|
bool headIsGreaterThanConstraint(Size size) {
|
|
if (type == ArrowType.left || type == ArrowType.right) {
|
|
return headHeight >= (size.width);
|
|
}
|
|
return headHeight >= (size.height);
|
|
}
|
|
|
|
public bool shouldRepaint(CustomPainter oldDelegate)
|
|
{
|
|
return !(oldDelegate is _ArrowPainter &&
|
|
headSize == ((_ArrowPainter)oldDelegate).headSize &&
|
|
strokeWidth == ((_ArrowPainter)oldDelegate).strokeWidth &&
|
|
color == ((_ArrowPainter)oldDelegate).color &&
|
|
type == ((_ArrowPainter)oldDelegate).type);
|
|
}
|
|
|
|
public void paint(Canvas canvas, Size size)
|
|
{
|
|
Paint paint = new Paint();
|
|
paint.color = color;
|
|
paint.strokeWidth = strokeWidth;
|
|
|
|
var originX = size.width / 2;
|
|
var originY = size.height / 2;
|
|
Offset lineStartingPoint = Offset.zero;
|
|
Offset lineEndingPoint = Offset.zero;
|
|
|
|
if (!headIsGreaterThanConstraint(size) && shouldDrawHead) {
|
|
Offset p1 = null, p2 = null, p3 = null;
|
|
var headSizeDividedBy2 = headSize / 2;
|
|
switch (type) {
|
|
case ArrowType.up:
|
|
p1 = new Offset(originX, 0);
|
|
p2 = new Offset(originX - headSizeDividedBy2, headHeight);
|
|
p3 = new Offset(originX + headSizeDividedBy2, headHeight);
|
|
break;
|
|
case ArrowType.left:
|
|
p1 = new Offset(0, originY);
|
|
p2 = new Offset(headHeight, originY - headSizeDividedBy2);
|
|
p3 = new Offset(headHeight, originY + headSizeDividedBy2);
|
|
break;
|
|
case ArrowType.right:
|
|
var startingX = size.width - headHeight;
|
|
p1 = new Offset(size.width, originY);
|
|
p2 = new Offset(startingX, originY - headSizeDividedBy2);
|
|
p3 = new Offset(startingX, originY + headSizeDividedBy2);
|
|
break;
|
|
case ArrowType.down:
|
|
var startingY = size.height - headHeight;
|
|
p1 = new Offset(originX, size.height);
|
|
p2 = new Offset(originX - headSizeDividedBy2, startingY);
|
|
p3 = new Offset(originX + headSizeDividedBy2, startingY);
|
|
break;
|
|
}
|
|
|
|
Path path = new Path();
|
|
|
|
path.moveTo(p1.dx, p1.dy);
|
|
path.lineTo(p2.dx, p2.dy);
|
|
path.lineTo(p3.dx, p3.dy);
|
|
path.close();
|
|
canvas.drawPath(path, paint);
|
|
|
|
switch (type) {
|
|
case ArrowType.up:
|
|
lineStartingPoint = new Offset(originX, headHeight);
|
|
lineEndingPoint = new Offset(originX, size.height);
|
|
break;
|
|
case ArrowType.left:
|
|
lineStartingPoint = new Offset(headHeight, originY);
|
|
lineEndingPoint = new Offset(size.width, originY);
|
|
break;
|
|
case ArrowType.right:
|
|
var arrowHeadStartingX = size.width - headHeight;
|
|
lineStartingPoint = new Offset(0, originY);
|
|
lineEndingPoint = new Offset(arrowHeadStartingX, originY);
|
|
break;
|
|
case ArrowType.down:
|
|
var headStartingY = size.height - headHeight;
|
|
lineStartingPoint = new Offset(originX, 0);
|
|
lineEndingPoint = new Offset(originX, headStartingY);
|
|
break;
|
|
}
|
|
} else {
|
|
// draw full line
|
|
switch (type) {
|
|
case ArrowType.up:
|
|
case ArrowType.down:
|
|
lineStartingPoint = new Offset(originX, 0);
|
|
lineEndingPoint = new Offset(originX, size.height);
|
|
break;
|
|
case ArrowType.left:
|
|
case ArrowType.right:
|
|
lineStartingPoint = new Offset(0, originY);
|
|
lineEndingPoint = new Offset(size.width, originY);
|
|
break;
|
|
}
|
|
}
|
|
canvas.drawLine(
|
|
lineStartingPoint,
|
|
lineEndingPoint,
|
|
paint
|
|
);
|
|
}
|
|
|
|
public bool? hitTest(Offset position)
|
|
{
|
|
throw new System.NotImplementedException();
|
|
}
|
|
|
|
public void addListener(VoidCallback listener)
|
|
{
|
|
throw new System.NotImplementedException();
|
|
}
|
|
|
|
public void removeListener(VoidCallback listener)
|
|
{
|
|
throw new System.NotImplementedException();
|
|
}
|
|
}
|
|
|
|
}
|