guanghuispark
4 年前
当前提交
b7dd4161
共有 11 个文件被更改,包括 1354 次插入 和 0 次删除
-
23com.unity.uiwidgets.devtools/Editor/enum_utils.cs
-
8com.unity.uiwidgets.devtools/Editor/theme.cs
-
450com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/box/box.cs
-
374com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/ui/arrow.cs
-
39com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/ui/dimension.cs
-
170com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/ui/free_space.cs
-
70com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/ui/overflow_indicator_painter.cs
-
220com.unity.uiwidgets.devtools/Editor/inspector/layout_explorer/ui/theme.cs
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.DevTools |
|||
{ |
|||
public class EnumUtils<T> { |
|||
|
|||
EnumUtils(List<T> enumValues) { |
|||
foreach (var val in enumValues) { |
|||
var enumDescription = DiagnosticUtils.describeEnum(val); |
|||
_lookupTable[enumDescription] = val; |
|||
_reverseLookupTable[val] = enumDescription; |
|||
} |
|||
} |
|||
Dictionary<string, T> _lookupTable = new Dictionary<string, T>(); |
|||
Dictionary<T, string> _reverseLookupTable = new Dictionary<T, string>(); |
|||
|
|||
T enumEntry(string enumName) => _lookupTable[enumName]; |
|||
|
|||
string name(T enumEntry) => _reverseLookupTable[enumEntry]; |
|||
} |
|||
|
|||
} |
|
|||
namespace Unity.UIWidgets.DevTools |
|||
{ |
|||
public class CommonThemeUtils |
|||
{ |
|||
public static readonly float denseSpacing = 8.0f; |
|||
public static readonly float defaultIconSize = 16.0f; |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.DevTools.inspector.layout_explorer.ui; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using ThemeUtils = Unity.UIWidgets.DevTools.inspector.layout_explorer.ui.ThemeUtils; |
|||
|
|||
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.box{ |
|||
|
|||
public class BoxUtils |
|||
{ |
|||
public static string describeBoxName(LayoutProperties properties) { |
|||
|
|||
var title = properties.node.description; |
|||
var renderDescription = properties.node?.renderObject?.description; |
|||
// TODO(jacobr): consider de-emphasizing the render object name by putting it
|
|||
// in more transparent text or just calling the widget Parent instead of
|
|||
// surfacing a widget name.
|
|||
if(renderDescription != null) { |
|||
title += " - $renderDescription"; |
|||
} |
|||
return title; |
|||
} |
|||
} |
|||
|
|||
public class BoxLayoutExplorerWidget : LayoutExplorerWidget { |
|||
public BoxLayoutExplorerWidget( |
|||
InspectorController inspectorController, |
|||
Key key |
|||
) : base(inspectorController, key: key){ } |
|||
|
|||
public static bool shouldDisplay(RemoteDiagnosticsNode node) { |
|||
// TODO(jacobr) pass a RemoteDiagnosticsNode to this method that contains
|
|||
// the layout explorer related supplemental properties so that we can
|
|||
// accurately determine whether the widget uses box layout.
|
|||
return node != null; |
|||
} |
|||
|
|||
|
|||
public override State createState() |
|||
{ |
|||
return new _BoxLayoutExplorerWidgetState(); |
|||
} |
|||
|
|||
} |
|||
|
|||
public class _BoxLayoutExplorerWidgetState : |
|||
LayoutExplorerWidgetState<BoxLayoutExplorerWidget, LayoutProperties> |
|||
{ |
|||
|
|||
public override RemoteDiagnosticsNode getRoot(RemoteDiagnosticsNode node) { |
|||
if (!shouldDisplay(node)) return null; |
|||
return node; |
|||
} |
|||
|
|||
|
|||
public override bool shouldDisplay(RemoteDiagnosticsNode node) { |
|||
return BoxLayoutExplorerWidget.shouldDisplay(selectedNode); |
|||
} |
|||
|
|||
|
|||
public override AnimatedLayoutProperties<LayoutProperties> computeAnimatedProperties( |
|||
LayoutProperties nextProperties |
|||
) { |
|||
return new AnimatedLayoutProperties<LayoutProperties>( |
|||
animatedProperties?.copyWith() ?? properties, |
|||
nextProperties, |
|||
changeAnimation |
|||
); |
|||
} |
|||
|
|||
|
|||
public override LayoutProperties computeLayoutProperties(RemoteDiagnosticsNode node) |
|||
{ |
|||
return new LayoutProperties(node); |
|||
} |
|||
|
|||
public override void updateHighlighted(LayoutProperties newProperties) { |
|||
setState(() =>{ |
|||
// This implementation will need to change if we support showing more than
|
|||
// a single widget in the box visualization for the layout explorer.
|
|||
if (newProperties != null && selectedNode == newProperties.node) { |
|||
highlighted = newProperties; |
|||
} else { |
|||
highlighted = null; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (properties == null) return new SizedBox(); |
|||
return new Container( |
|||
margin: EdgeInsets.all(ThemeUtils.margin), |
|||
padding: EdgeInsets.only(bottom: ThemeUtils.margin, right: ThemeUtils.margin), |
|||
child: new AnimatedBuilder( |
|||
animation: changeController, |
|||
builder: (context2, _) => { |
|||
return new LayoutBuilder(builder: _buildLayout); |
|||
} |
|||
) |
|||
); |
|||
} |
|||
|
|||
/// TODO(jacobr): see if we can unify with the stylized version of the overall
|
|||
/// layout used for Flex. Our constraints are quite different as we can
|
|||
/// guarantee that the entire layout fits without scrolling while in the Flex
|
|||
/// case that would be difficult.
|
|||
|
|||
static List<float?> minFractionLayout( |
|||
float? availableSize, |
|||
List<float?> sizes, |
|||
List<float?> minFractions |
|||
) { |
|||
D.assert(sizes.Count == minFractions.Count); |
|||
var length = sizes.Count; |
|||
float total = 1.0f; |
|||
var fractions = minFractions.ToList(); |
|||
foreach (var size in sizes) { |
|||
if (size != null) { |
|||
total += Mathf.Max(0, size.Value); |
|||
} |
|||
} |
|||
|
|||
float totalFraction = 0.0f; |
|||
for (int i = 0; i < length; i++) { |
|||
var size = sizes[i]; |
|||
if (size != null) { |
|||
fractions[i] = Mathf.Max(size.Value / total, minFractions[i]?? 0.0f); |
|||
totalFraction += fractions[i].Value; |
|||
} else { |
|||
fractions[i] = 0.0f; |
|||
} |
|||
} |
|||
if (Mathf.Abs(totalFraction - 1.0f) > 1E-10) { |
|||
for (int i = 0; i < length; i++) { |
|||
fractions[i] = fractions[i] / totalFraction; |
|||
} |
|||
} |
|||
var output = new List<float?>(); |
|||
foreach (var fraction in fractions) { |
|||
output.Add(fraction * availableSize); |
|||
} |
|||
return output; |
|||
} |
|||
|
|||
public Widget _buildChild(BuildContext context) { |
|||
var theme = Theme.of(context); |
|||
var colorScheme = theme.colorScheme; |
|||
var parentProperties = this.parentProperties ?? properties; |
|||
|
|||
var parentSize = parentProperties.size; |
|||
var boxParentData = new BoxParentData(); |
|||
boxParentData.offset = new Offset(0, 0); |
|||
var offset = properties.node?.parentData ?? boxParentData; |
|||
|
|||
if (properties.size == null) { |
|||
return new Center( |
|||
child: new Text( |
|||
"Visualizing layouts for ${properties.description} widgets is not yet supported." |
|||
) |
|||
); |
|||
} |
|||
return new LayoutBuilder( |
|||
builder: (BuildContext context2, BoxConstraints constraints) => |
|||
{ |
|||
// Subtract out one pixel border on each side.
|
|||
var availableHeight = constraints.maxHeight - 2; |
|||
var availableWidth = constraints.maxWidth - 2; |
|||
|
|||
var minFractions = new List<float?> {0.2f, 0.5f, 0.2f}; |
|||
|
|||
float? nullOutZero(float value) |
|||
{ |
|||
return value != 0.0f ? value : (float?) null; |
|||
} |
|||
|
|||
var widths = new List<float?> |
|||
{ |
|||
nullOutZero(offset.offset.dx), |
|||
properties.size.width, |
|||
nullOutZero(parentSize != null |
|||
? parentSize.width - (properties.size.width + offset.offset.dx) |
|||
: 0.0f) |
|||
}; |
|||
var heights = new List<float?> |
|||
{ |
|||
nullOutZero(offset.offset.dy), |
|||
properties.size.height, |
|||
nullOutZero(parentSize != null |
|||
? parentSize.height - (properties.size.height + offset.offset.dy) |
|||
: 0.0f) |
|||
}; |
|||
// 3 element array with [left padding, widget width, right padding].
|
|||
var displayWidths = minFractionLayout( |
|||
availableSize: availableWidth, |
|||
sizes: widths, |
|||
minFractions: minFractions |
|||
); |
|||
// 3 element array with [top padding, widget height, bottom padding].
|
|||
var displayHeights = minFractionLayout( |
|||
availableSize: availableHeight, |
|||
sizes: heights, |
|||
minFractions: minFractions |
|||
); |
|||
var widgetWidth = displayWidths[1]; |
|||
var widgetHeight = displayHeights[1]; |
|||
var safeParentSize = parentSize ?? properties.size; |
|||
|
|||
List<Widget> widgets = new List<Widget>(); |
|||
widgets.Add(new LayoutExplorerBackground(colorScheme: colorScheme)); |
|||
if (widths[0] != null) |
|||
{ |
|||
widgets.Add(new PaddingVisualizerWidget( |
|||
new RenderProperties( |
|||
axis: Axis.horizontal, |
|||
size: new Size(displayWidths[0].Value, widgetHeight.Value), |
|||
offset: new Offset(0, displayHeights[0].Value), |
|||
realSize: new Size(widths[0].Value, safeParentSize.height), |
|||
layoutProperties: properties, |
|||
isFreeSpace: true |
|||
), |
|||
horizontal: true |
|||
)); |
|||
} |
|||
|
|||
if (heights[0] != null) |
|||
{ |
|||
widgets.Add(new PaddingVisualizerWidget( |
|||
new RenderProperties( |
|||
axis: Axis.horizontal, |
|||
size: new Size(widgetWidth.Value, displayHeights[0].Value), |
|||
offset: new Offset(displayWidths[0].Value, 0), |
|||
realSize: new Size(safeParentSize.width, heights[0].Value), |
|||
layoutProperties: properties, |
|||
isFreeSpace: true |
|||
), |
|||
horizontal: false |
|||
)); |
|||
} |
|||
|
|||
if (widths[2] != null) |
|||
{ |
|||
widgets.Add(new PaddingVisualizerWidget( |
|||
new RenderProperties( |
|||
axis: Axis.horizontal, |
|||
size: new Size(displayWidths[2].Value, widgetHeight.Value), |
|||
offset: new Offset( |
|||
displayWidths[0].Value + displayWidths[1].Value, displayHeights[0].Value), |
|||
realSize: new Size(widths[2].Value, safeParentSize.height), |
|||
layoutProperties: properties, |
|||
isFreeSpace: true |
|||
), |
|||
horizontal: true |
|||
)); |
|||
} |
|||
|
|||
if (heights[2] != null) |
|||
{ |
|||
widgets.Add(new PaddingVisualizerWidget( |
|||
new RenderProperties( |
|||
axis: Axis.horizontal, |
|||
size: new Size(widgetWidth.Value, displayHeights[2].Value), |
|||
offset: new Offset(displayWidths[0].Value, |
|||
displayHeights[0].Value + displayHeights[1].Value), |
|||
realSize: new Size(safeParentSize.width, heights[2].Value), |
|||
layoutProperties: properties, |
|||
isFreeSpace: true |
|||
), |
|||
horizontal: false |
|||
)); |
|||
} |
|||
widgets.Add(new BoxChildVisualizer( |
|||
isSelected: true, |
|||
state: this, |
|||
layoutProperties: properties, |
|||
renderProperties: |
|||
new RenderProperties( |
|||
axis: Axis.horizontal, |
|||
size: new Size(widgetWidth.Value, widgetHeight.Value), |
|||
offset: new Offset(displayWidths[0].Value, displayHeights[0].Value), |
|||
realSize: properties.size, |
|||
layoutProperties: properties |
|||
) |
|||
)); |
|||
|
|||
|
|||
return new Container( |
|||
width: constraints.maxWidth, |
|||
height: constraints.maxHeight, |
|||
decoration: new BoxDecoration( |
|||
border: Border.all( |
|||
color: ThemeUtils.regularWidgetColor |
|||
) |
|||
), |
|||
child: new Stack( |
|||
children: widgets |
|||
) |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
LayoutProperties parentProperties { |
|||
get |
|||
{ |
|||
var parentElement = properties?.node?.parentRenderElement; |
|||
if (parentElement == null) return null; |
|||
var parentProperties = computeLayoutProperties(parentElement); |
|||
if (parentProperties.size == null) return null; |
|||
return parentProperties; |
|||
} |
|||
|
|||
} |
|||
|
|||
Widget _buildLayout(BuildContext context, BoxConstraints constraints) { |
|||
var maxHeight = constraints.maxHeight; |
|||
var maxWidth = constraints.maxWidth; |
|||
|
|||
Widget widget = _buildChild(context); |
|||
var parentProperties = this.parentProperties; |
|||
if (parentProperties != null) { |
|||
widget = new WidgetVisualizer( |
|||
// TODO(jacobr): this node's name can be misleading more often than
|
|||
// in the flex case the widget doesn't have its own RenderObject.
|
|||
// Consider showing the true ancestor for the summary tree that first
|
|||
// has a different render object.
|
|||
title: BoxUtils.describeBoxName(parentProperties), |
|||
largeTitle: true, |
|||
layoutProperties: parentProperties, |
|||
isSelected: false, |
|||
child: new VisualizeWidthAndHeightWithConstraints( |
|||
properties: parentProperties, |
|||
warnIfUnconstrained: false, |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(CommonThemeUtils.denseSpacing), |
|||
child: widget |
|||
) |
|||
) |
|||
); |
|||
} |
|||
return new Container( |
|||
constraints: new BoxConstraints(maxWidth: maxWidth, maxHeight: maxHeight), |
|||
child: widget |
|||
); |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
public class BoxChildVisualizer : StatelessWidget { |
|||
public BoxChildVisualizer( |
|||
Key key = null, |
|||
_BoxLayoutExplorerWidgetState state = null, |
|||
LayoutProperties layoutProperties = null, |
|||
RenderProperties renderProperties = null, |
|||
bool isSelected = false |
|||
) : base(key: key) |
|||
{ |
|||
this.state = state; |
|||
this.layoutProperties = layoutProperties; |
|||
this.renderProperties = renderProperties; |
|||
this.isSelected = isSelected; |
|||
} |
|||
|
|||
public readonly _BoxLayoutExplorerWidgetState state; |
|||
|
|||
public readonly bool isSelected; |
|||
public readonly LayoutProperties layoutProperties; |
|||
public readonly RenderProperties renderProperties; |
|||
|
|||
public LayoutProperties root |
|||
{ |
|||
get |
|||
{ |
|||
return state.properties; |
|||
} |
|||
} |
|||
|
|||
public LayoutProperties properties |
|||
{ |
|||
get |
|||
{ |
|||
return renderProperties.layoutProperties; |
|||
} |
|||
} |
|||
|
|||
|
|||
public override Widget build(BuildContext context2) { |
|||
var renderSize = renderProperties.size; |
|||
var renderOffset = renderProperties.offset; |
|||
|
|||
Widget buildEntranceAnimation(BuildContext context3, Widget child) { |
|||
var size = renderSize; |
|||
// TODO(jacobr): does this entrance animation really add value.
|
|||
return new Opacity( |
|||
opacity: Mathf.Min(state.entranceCurve.value * 5, 1.0f), |
|||
child: new Padding( |
|||
padding: EdgeInsets.symmetric( |
|||
horizontal: Mathf.Max(0.0f, (renderSize.width - size.width) / 2), |
|||
vertical: Mathf.Max(0.0f, (renderSize.height - size.height) / 2) |
|||
), |
|||
child: child |
|||
) |
|||
); |
|||
} |
|||
|
|||
return new Positioned( |
|||
top: renderOffset.dy, |
|||
left: renderOffset.dx, |
|||
child: new InkWell( |
|||
onTap: () => state.onTap(properties), |
|||
onDoubleTap: () => state.onDoubleTap(properties), |
|||
onLongPress: () => state.onDoubleTap(properties), |
|||
child: new SizedBox( |
|||
width: utils.safePositiveFloat(renderSize.width), |
|||
height: utils.safePositiveFloat(renderSize.height), |
|||
child: new AnimatedBuilder( |
|||
animation: state.entranceController, |
|||
builder: buildEntranceAnimation, |
|||
child: new WidgetVisualizer( |
|||
isSelected: isSelected, |
|||
layoutProperties: layoutProperties, |
|||
title: BoxUtils.describeBoxName(properties), |
|||
// TODO(jacobr): consider surfacing the overflow size information
|
|||
// if we determine
|
|||
// overflowSide: properties.overflowSide,
|
|||
|
|||
// We only show one child at a time so a large title is safe.
|
|||
largeTitle: true, |
|||
child: new VisualizeWidthAndHeightWithConstraints( |
|||
arrowHeadSize: ThemeUtils.arrowHeadSize, |
|||
properties: properties, |
|||
warnIfUnconstrained: false, |
|||
child: null |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
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(); |
|||
} |
|||
} |
|||
|
|||
} |
|
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.ui |
|||
{ |
|||
public class Dimension |
|||
{ |
|||
public static Widget dimensionDescription( |
|||
TextSpan description, |
|||
bool overflow, |
|||
ColorScheme colorScheme |
|||
) { |
|||
var text = Text.rich( |
|||
description, |
|||
textAlign: TextAlign.center, |
|||
style: |
|||
ThemeUtils.dimensionIndicatorTextStyle, |
|||
overflow: TextOverflow.ellipsis |
|||
); |
|||
if (overflow) { |
|||
return new Container( |
|||
padding: EdgeInsets.symmetric( |
|||
vertical: ThemeUtils.minPadding, |
|||
horizontal: ThemeUtils.overflowTextHorizontalPadding |
|||
), |
|||
decoration: new BoxDecoration( |
|||
color: ThemeUtils.overflowBackgroundColor, |
|||
borderRadius: BorderRadius.circular(4.0f) |
|||
), |
|||
child: new Center(child: text) |
|||
); |
|||
} |
|||
return text; |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.ui |
|||
{ |
|||
public class FreeSpaceVisualizerWidget : StatelessWidget { |
|||
public FreeSpaceVisualizerWidget( |
|||
RenderProperties renderProperties, |
|||
Key key = null |
|||
) : base(key: key) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public readonly RenderProperties renderProperties; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
var colorScheme = Theme.of(context).colorScheme; |
|||
var heightDescription = |
|||
$"h={renderProperties.realHeight}"; |
|||
var widthDescription = $"w={renderProperties.realWidth}"; |
|||
var showWidth = renderProperties.realWidth != |
|||
(renderProperties.layoutProperties?.width); |
|||
var widthWidget = new Container( |
|||
child: new Column( |
|||
mainAxisAlignment: MainAxisAlignment.center, |
|||
children: new List<Widget>{ |
|||
new Flexible( |
|||
child: Dimension.dimensionDescription( |
|||
new TextSpan( |
|||
text: widthDescription |
|||
), |
|||
false, |
|||
colorScheme |
|||
) |
|||
), |
|||
new Container( |
|||
margin: EdgeInsets.symmetric(vertical: ThemeUtils.arrowMargin), |
|||
child: new ArrowWrapper( |
|||
arrowColor: ThemeUtils.widthIndicatorColor, |
|||
direction: Axis.horizontal, |
|||
arrowHeadSize: ThemeUtils.arrowHeadSize |
|||
) |
|||
), |
|||
} |
|||
) |
|||
); |
|||
var heightWidget = new Container( |
|||
width: ThemeUtils.heightOnlyIndicatorSize, |
|||
child: new Row( |
|||
mainAxisAlignment: MainAxisAlignment.center, |
|||
children: new List<Widget>{ |
|||
new Flexible( |
|||
child: Dimension.dimensionDescription( |
|||
new TextSpan(text: heightDescription), |
|||
false, |
|||
colorScheme |
|||
) |
|||
), |
|||
new Container( |
|||
margin: EdgeInsets.symmetric(horizontal: ThemeUtils.arrowMargin), |
|||
child: new ArrowWrapper( |
|||
arrowColor: ThemeUtils.heightIndicatorColor, |
|||
direction: Axis.vertical, |
|||
arrowHeadSize: ThemeUtils.arrowHeadSize, |
|||
childMarginFromArrow: 0.0f |
|||
) |
|||
) |
|||
} |
|||
) |
|||
); |
|||
return new Positioned( |
|||
top: renderProperties.offset.dy, |
|||
left: renderProperties.offset.dx, |
|||
child: new Container( |
|||
width: renderProperties.width, |
|||
height: renderProperties.height, |
|||
child: new Tooltip( |
|||
message: $"{widthDescription}\n{heightDescription}", |
|||
child: showWidth ? widthWidget : heightWidget |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class PaddingVisualizerWidget : StatelessWidget { |
|||
public PaddingVisualizerWidget( |
|||
RenderProperties renderProperties, |
|||
bool horizontal, |
|||
Key key = null |
|||
) : base(key: key) |
|||
{ |
|||
this.renderProperties = renderProperties; |
|||
this.horizontal = horizontal; |
|||
} |
|||
|
|||
public readonly RenderProperties renderProperties; |
|||
public readonly bool horizontal; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
var colorScheme = Theme.of(context).colorScheme; |
|||
var heightDescription = |
|||
$"h={renderProperties.realHeight}"; |
|||
var widthDescription = $"w={renderProperties.realWidth}"; |
|||
var widthWidget = new Container(child: |
|||
new Column( |
|||
mainAxisAlignment: MainAxisAlignment.center, |
|||
children: new List<Widget>{ |
|||
new Flexible( |
|||
child: Dimension.dimensionDescription( |
|||
new TextSpan( |
|||
text: widthDescription |
|||
), |
|||
false, |
|||
colorScheme |
|||
) |
|||
), |
|||
new Container( |
|||
margin: EdgeInsets.symmetric(vertical: ThemeUtils.arrowMargin), |
|||
child: new ArrowWrapper( |
|||
arrowColor: ThemeUtils.widthIndicatorColor, |
|||
direction: Axis.horizontal, |
|||
arrowHeadSize: ThemeUtils.arrowHeadSize |
|||
) |
|||
) |
|||
} |
|||
) |
|||
); |
|||
var heightWidget = new Container( |
|||
width: ThemeUtils.heightOnlyIndicatorSize, |
|||
child: new Row( |
|||
mainAxisAlignment: MainAxisAlignment.center, |
|||
children: new List<Widget>{ |
|||
new Flexible( |
|||
child: Dimension.dimensionDescription( |
|||
new TextSpan(text: heightDescription), |
|||
false, |
|||
colorScheme |
|||
) |
|||
), |
|||
new Container( |
|||
margin: EdgeInsets.symmetric(horizontal: ThemeUtils.arrowMargin), |
|||
child: new ArrowWrapper( |
|||
arrowColor: ThemeUtils.heightIndicatorColor, |
|||
direction: Axis.vertical, |
|||
arrowHeadSize: ThemeUtils.arrowHeadSize, |
|||
childMarginFromArrow: 0.0f |
|||
) |
|||
) |
|||
} |
|||
) |
|||
); |
|||
return new Positioned( |
|||
top: renderProperties.offset.dy, |
|||
left: renderProperties.offset.dx, |
|||
child: new Container( |
|||
width: utils.safePositiveFloat(renderProperties.width), |
|||
height: utils.safePositiveFloat(renderProperties.height), |
|||
child: horizontal ? widthWidget : heightWidget |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.ui |
|||
{ |
|||
public class OverflowIndicatorPainter : CustomPainter { |
|||
public OverflowIndicatorPainter(OverflowSide side, float size) |
|||
{ |
|||
this.side = side; |
|||
this.size = size; |
|||
indicatorPaint.shader = Gradient.linear( |
|||
new Offset(0.0f, 0.0f), |
|||
new Offset(10.0f, 10.0f), |
|||
|
|||
new List<Color>{ |
|||
black, yellow, yellow, black |
|||
}, |
|||
|
|||
new List<float>{ |
|||
0.25f, 0.25f, 0.75f, 0.75f |
|||
}, |
|||
TileMode.repeated |
|||
); |
|||
} |
|||
|
|||
public readonly OverflowSide side; |
|||
public readonly float size; |
|||
|
|||
Color black = new Color(0xBF000000); |
|||
Color yellow = new Color(0xBFFFFF00); |
|||
Paint indicatorPaint = new Paint(); |
|||
|
|||
|
|||
|
|||
public void paint(Canvas canvas, Size size) { |
|||
var bottomOverflow = OverflowSide.bottom == side; |
|||
var width = bottomOverflow ? size.width : this.size; |
|||
var height = !bottomOverflow ? size.height : this.size; |
|||
|
|||
var left = bottomOverflow ? 0.0f : size.width - width; |
|||
var top = side == OverflowSide.right ? 0.0f : size.height - height; |
|||
var rect = Rect.fromLTWH(left, top, width, height); |
|||
|
|||
canvas.drawRect(rect, indicatorPaint); |
|||
} |
|||
|
|||
|
|||
public bool shouldRepaint(CustomPainter oldDelegate) { |
|||
return oldDelegate is OverflowIndicatorPainter && |
|||
(side != ((OverflowIndicatorPainter)oldDelegate).side || size != ((OverflowIndicatorPainter)oldDelegate).size); |
|||
} |
|||
|
|||
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(); |
|||
} |
|||
} |
|||
|
|||
} |
|
|||
using uiwidgets; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace Unity.UIWidgets.DevTools.inspector.layout_explorer.ui |
|||
{ |
|||
public class ThemeUtils |
|||
{ |
|||
public static readonly float margin = 8.0f; |
|||
|
|||
public static readonly float arrowHeadSize = 8.0f; |
|||
public static readonly float arrowMargin = 4.0f; |
|||
public static readonly float arrowStrokeWidth = 1.5f; |
|||
|
|||
/// Hardcoded sizes for scaling the flex children widget properly.
|
|||
public static readonly float minRenderWidth = 250.0f; |
|||
public static readonly float minRenderHeight = 250.0f; |
|||
|
|||
public static readonly float minPadding = 2.0f; |
|||
public static readonly float overflowTextHorizontalPadding = 8.0f; |
|||
|
|||
/// The size to shrink a widget by when animating it in.
|
|||
public static readonly float entranceMargin = 50.0f; |
|||
|
|||
public static readonly float defaultMaxRenderWidth = 400.0f; |
|||
public static readonly float defaultMaxRenderHeight = 400.0f; |
|||
|
|||
public static readonly float widgetTitleMaxWidthPercentage = 0.75f; |
|||
|
|||
/// Hardcoded arrow size respective to its cross axis (because it's unconstrained).
|
|||
public static readonly float heightAndConstraintIndicatorSize = 48.0f; |
|||
public static readonly float widthAndConstraintIndicatorSize = 56.0f; |
|||
public static readonly float mainAxisArrowIndicatorSize = 48.0f; |
|||
public static readonly float crossAxisArrowIndicatorSize = 48.0f; |
|||
|
|||
public static readonly float heightOnlyIndicatorSize = 72.0f; |
|||
public static readonly float widthOnlyIndicatorSize = 32.0f; |
|||
|
|||
/// Minimum size to display width/height inside the arrow
|
|||
public static readonly float minWidthToDisplayWidthInsideArrow = 200.0f; |
|||
public static readonly float minHeightToDisplayHeightInsideArrow = 200.0f; |
|||
|
|||
public static readonly float largeTextScaleFactor = 1.2f; |
|||
public static readonly float smallTextScaleFactor = 0.8f; |
|||
|
|||
/// Height for limiting asset image (selected one in the drop down).
|
|||
public static readonly float axisAlignmentAssetImageHeight = 24.0f; |
|||
|
|||
/// Width for limiting asset image (when drop down menu is open for the vertical).
|
|||
public static readonly float axisAlignmentAssetImageWidth = 96.0f; |
|||
public static readonly float dropdownMaxSize = 220.0f; |
|||
|
|||
public static readonly float minHeightToAllowTruncating = 375.0f; |
|||
public static readonly float minWidthToAllowTruncating = 375.0f; |
|||
|
|||
// Story of Layout colors
|
|||
public static readonly Color mainAxisLightColor = new Color(0xff2c5daa); |
|||
public static readonly Color mainAxisDarkColor = new Color(0xff2c5daa); |
|||
public static readonly Color rowColor = new Color(0xff2c5daa); |
|||
public static readonly Color columnColor = new Color(0xff77974d); |
|||
public static readonly Color regularWidgetColor = new Color(0xff88b1de); |
|||
|
|||
public static readonly Color selectedWidgetColor = new Color(0xff36c6f4); |
|||
|
|||
public static readonly Color textColor = new Color(0xff55767f); |
|||
public static readonly Color emphasizedTextColor = new Color(0xff009aca); |
|||
|
|||
public static readonly Color crossAxisLightColor = new Color(0xff8ac652); |
|||
public static readonly Color crossAxisDarkColor = new Color(0xff8ac652); |
|||
|
|||
public static readonly Color mainAxisTextColorLight = new Color(0xFF1375bc); |
|||
public static readonly Color mainAxisTextColorDark = new Color(0xFF1375bc); |
|||
|
|||
public static readonly Color crossAxisTextColorLight = new Color(0xFF66672C); |
|||
public static readonly Color crossAxisTextColorsDark = new Color(0xFFB3D25A); |
|||
|
|||
public static readonly Color overflowBackgroundColorDark = new Color(0xFFB00020); |
|||
public static readonly Color overflowBackgroundColorLight = new Color(0xFFB00020); |
|||
|
|||
public static readonly Color overflowTextColorDark = new Color(0xfff5846b); |
|||
public static readonly Color overflowTextColorLight = new Color(0xffdea089); |
|||
|
|||
public static readonly Color backgroundColorSelectedDark = new Color( |
|||
0x4d474747); // TODO(jacobr): we would like Color(0x4dedeeef) but that makes the background show through.
|
|||
public static readonly Color backgroundColorSelectedLight = new Color(0x4dedeeef); |
|||
|
|||
public static bool isLight = false; |
|||
|
|||
public static Color mainAxisColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight? mainAxisLightColor : mainAxisDarkColor; |
|||
} |
|||
} |
|||
|
|||
public static Color widgetNameColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? Colors.white : Colors.black; |
|||
} |
|||
} |
|||
|
|||
public static Color crossAxisColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? crossAxisLightColor : crossAxisDarkColor; |
|||
} |
|||
} |
|||
|
|||
public static Color mainAxisTextColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? mainAxisTextColorLight : mainAxisTextColorDark; |
|||
} |
|||
} |
|||
|
|||
public static Color crossAxisTextColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? crossAxisTextColorLight : crossAxisTextColorsDark; |
|||
} |
|||
} |
|||
|
|||
public static Color overflowBackgroundColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? overflowBackgroundColorLight : overflowBackgroundColorDark; |
|||
} |
|||
} |
|||
|
|||
public static Color overflowTextColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? overflowTextColorLight : overflowTextColorDark; |
|||
} |
|||
} |
|||
|
|||
public static Color backgroundColorSelected |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? backgroundColorSelectedLight : backgroundColorSelectedDark; |
|||
} |
|||
} |
|||
|
|||
public static Color backgroundColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? backgroundColorLight : backgroundColorDark; |
|||
} |
|||
} |
|||
|
|||
public static Color unconstrainedColor |
|||
{ |
|||
get |
|||
{ |
|||
return isLight ? unconstrainedLightColor : unconstrainedDarkColor; |
|||
} |
|||
} |
|||
|
|||
|
|||
public static readonly Color backgroundColorDark = new Color(0xff30302f); |
|||
public static readonly Color backgroundColorLight = new Color(0xffffffff); |
|||
|
|||
public static readonly Color unconstrainedDarkColor = new Color(0xffdea089); |
|||
public static readonly Color unconstrainedLightColor = new Color(0xfff5846b); |
|||
|
|||
public static readonly Color widthIndicatorColor = textColor; |
|||
public static readonly Color heightIndicatorColor = textColor; |
|||
|
|||
public static readonly string negativeSpaceDarkAssetName = |
|||
"assets/img/layout_explorer/negative_space_dark.png"; |
|||
public static readonly string negativeSpaceLightAssetName = |
|||
"assets/img/layout_explorer/negative_space_light.png"; |
|||
|
|||
public static TextStyle dimensionIndicatorTextStyle = new TextStyle( |
|||
height: 1.0f, |
|||
letterSpacing: 1.1f, |
|||
color: emphasizedTextColor |
|||
); |
|||
|
|||
public static TextStyle overflowingDimensionIndicatorTextStyle(ColorScheme colorScheme) |
|||
{ |
|||
|
|||
return new TextStyle( |
|||
height: 1.0f, |
|||
letterSpacing: 1.1f, |
|||
color: overflowTextColor, |
|||
fontWeight: FontWeight.bold |
|||
); |
|||
} |
|||
|
|||
public Widget buildUnderline() { |
|||
return new Container( |
|||
height: 1.0f, |
|||
decoration: new BoxDecoration( |
|||
border: new Border( |
|||
bottom: new BorderSide( |
|||
color: textColor, |
|||
width: 0.0f |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue