Skip to content

Commit

Permalink
Merge pull request #66 from Clancey/jon/dev
Browse files Browse the repository at this point in the history
Started work on shape support on UWP.  (Not completely, pivoting to w…
  • Loading branch information
jonlipsky committed Jul 23, 2019
2 parents fd6d881 + 57612ac commit 851d1b4
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 15 deletions.
62 changes: 62 additions & 0 deletions src/HotUI.UWP/Controls/HUIShapeView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Windows.Foundation;
using Windows.UI.Xaml.Media;
using WCanvas = Windows.UI.Xaml.Controls.Canvas;
using WPath = Windows.UI.Xaml.Shapes.Path;

namespace HotUI.UWP.Controls
{
public class HUIShapeView : WCanvas
{
private Shape _shape;
private WPath _path;
private Size _size;

public HUIShapeView()
{

}

public Shape Shape
{
get => _shape;
set
{
_shape = value;
UpdateShape();
}
}

public View View { get; set; }

protected override Size ArrangeOverride(Size finalSize)
{
_size = base.ArrangeOverride(finalSize);
UpdateShape();
return _size;
}

private void UpdateShape()
{
if (_path != null)
{
Children.Remove(_path);
_path = null;
}

if (_shape != null)
{
if (_size.Width <= 0 || _size.Height <= 0) return;

var bounds = new RectangleF(0, 0, (float)_size.Width, (float)_size.Height);
var path = _shape.PathForBounds(bounds);
_path = new WPath()
{
Data = path.AsPathGeometry(),
Stroke = new SolidColorBrush(_shape.GetColor(View, Color.Black).ToColor()),
StrokeThickness = _shape.GetStroke(View,1)
};
Children.Add(_path);
}
}
}
}
6 changes: 6 additions & 0 deletions src/HotUI.UWP/FoundationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Windows.UI.Input;
using UWPSize = Windows.Foundation.Size;
using UWPRect = Windows.Foundation.Rect;
using UWPPoint = Windows.Foundation.Point;

namespace HotUI.UWP
{
Expand Down Expand Up @@ -32,5 +33,10 @@ public static UWPRect ToRect(this RectangleF rect)
{
return new UWPRect(rect.X, rect.Y, rect.Width, rect.Height);
}

public static UWPPoint ToPoint(this PointF point)
{
return new UWPPoint(point.X, point.Y);
}
}
}
123 changes: 109 additions & 14 deletions src/HotUI.UWP/GraphicsExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HotUI.Graphics;
using System;
using Windows.UI.Xaml.Media;
using UWPSize = Windows.Foundation.Size;
using UWPColor = Windows.UI.Color;

namespace HotUI.UWP
{
public static class GraphicsExtensions
{
public static Task<ImageSource> LoadImage(this string source)
{
public static UWPColor ToColor(this Color target)
{
throw new NotImplementedException();
return UWPColor.FromArgb(
(byte)(255 * target.A),
(byte)(255 * target.R),
(byte)(255 * target.G),
(byte)(255 * target.B));
}

private static Task<ImageSource> LoadImageAsync(string urlString)
public static PathGeometry AsPathGeometry(this PathF target)
{
throw new NotImplementedException();
var geometry = new PathGeometry();
PathFigure figure = null;

}
var pointIndex = 0;
var arcAngleIndex = 0;
var arcClockwiseIndex = 0;

private static Task<ImageSource> LoadFileAsync(string filePath)
{
throw new NotImplementedException();
foreach (var operation in target.PathOperations)
{
if (operation == PathOperation.MoveTo)
{
figure = new PathFigure();
geometry.Figures.Add(figure);
figure.StartPoint = target[pointIndex++].ToPoint();
}
else if (operation == PathOperation.Line)
{
var lineSegment = new LineSegment { Point = target[pointIndex++].ToPoint() };
figure.Segments.Add(lineSegment);
}
else if (operation == PathOperation.Quad)
{
var quadSegment = new QuadraticBezierSegment
{
Point1 = target[pointIndex++].ToPoint(),
Point2 = target[pointIndex++].ToPoint()
};
figure.Segments.Add(quadSegment);
}
else if (operation == PathOperation.Cubic)
{
var cubicSegment = new BezierSegment()
{
Point1 = target[pointIndex++].ToPoint(),
Point2 = target[pointIndex++].ToPoint(),
Point3 = target[pointIndex++].ToPoint(),
};
figure.Segments.Add(cubicSegment);
}
else if (operation == PathOperation.Arc)
{
var topLeft = target[pointIndex++];
var bottomRight = target[pointIndex++];
var startAngle = target.GetArcAngle(arcAngleIndex++);
var endAngle = target.GetArcAngle(arcAngleIndex++);
var clockwise = target.IsArcClockwise(arcClockwiseIndex++);

while (startAngle < 0)
{
startAngle += 360;
}

while (endAngle < 0)
{
endAngle += 360;
}

var sweep = GraphicsOperations.GetSweep(startAngle, endAngle, clockwise);
var absSweep = Math.Abs(sweep);

var rectX = topLeft.X;
var rectY = topLeft.Y;
var rectWidth = bottomRight.X - topLeft.X;
var rectHeight = bottomRight.Y - topLeft.Y;

var startPoint = GraphicsOperations.OvalAngleToPoint(rectX, rectY, rectWidth, rectHeight, -startAngle);
var endPoint = GraphicsOperations.OvalAngleToPoint(rectX, rectY, rectWidth, rectHeight, -endAngle);

if (figure == null)
{
figure = new PathFigure();
geometry.Figures.Add(figure);
figure.StartPoint = startPoint.ToPoint();
}
else
{
var lineSegment = new LineSegment()
{
Point = startPoint.ToPoint()
};
figure.Segments.Add(lineSegment);
}

var arcSegment = new ArcSegment()
{
Point = endPoint.ToPoint(),
Size = new UWPSize(rectWidth / 2, rectHeight / 2),
SweepDirection = clockwise ? SweepDirection.Clockwise : SweepDirection.Counterclockwise,
IsLargeArc = absSweep >= 180,
};
figure.Segments.Add(arcSegment);
}
else if (operation == PathOperation.Close)
{
figure.IsClosed = true;
}
}

return geometry;
}
}
}
37 changes: 37 additions & 0 deletions src/HotUI.UWP/Handlers/ShapeViewHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@


// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable MemberCanBePrivate.Global

using HotUI.UWP.Controls;

namespace HotUI.UWP.Handlers
{
public class ShapeViewHandler : AbstractControlHandler<ShapeView, HUIShapeView>
{
public static readonly PropertyMapper<ShapeView> Mapper = new PropertyMapper<ShapeView>(ViewHandler.Mapper)
{
[nameof(HotUI.ShapeView.Shape)] = MapShapeProperty,
};


public ShapeViewHandler() : base(Mapper)
{

}

protected override HUIShapeView CreateView() => new HUIShapeView();

protected override void DisposeView(HUIShapeView nativeView)
{

}

public static void MapShapeProperty(IViewHandler viewHandler, ShapeView virtualView)
{
var nativeView = (HUIShapeView) viewHandler.NativeView;
nativeView.View = virtualView;
nativeView.Shape = virtualView.Shape;
}
}
}
24 changes: 24 additions & 0 deletions src/HotUI.UWP/Handlers/ViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ namespace HotUI.UWP.Handlers
{
public class ViewHandler : AbstractHandler<View, UIElement>
{
public static readonly PropertyMapper<View> Mapper = new PropertyMapper<View>()
{
[nameof(EnvironmentKeys.Colors.BackgroundColor)] = MapBackgroundColorProperty,
[nameof(EnvironmentKeys.View.Shadow)] = MapShadowProperty,
[nameof(EnvironmentKeys.View.ClipShape)] = MapClipShapeProperty,
[nameof(EnvironmentKeys.View.Overlay)] = MapOverlayProperty,
};

protected override UIElement CreateView()
{
var viewHandler = VirtualView?.GetOrCreateViewHandler();
Expand All @@ -19,5 +27,21 @@ protected override UIElement CreateView()

return viewHandler?.View;
}

private static void MapOverlayProperty(IViewHandler arg1, View arg2)
{
}

private static void MapClipShapeProperty(IViewHandler arg1, View arg2)
{
}

private static void MapShadowProperty(IViewHandler arg1, View arg2)
{
}

private static void MapBackgroundColorProperty(IViewHandler arg1, View arg2)
{
}
}
}
2 changes: 2 additions & 0 deletions src/HotUI.UWP/HotUI.UWP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Controls\HUIListCell.cs" />
<Compile Include="Controls\HUIShapeView.cs" />
<Compile Include="Graphics\UWPBitmap.cs" />
<Compile Include="Handlers\AbstractHandler.cs" />
<Compile Include="Controls\HUIContainerView.cs" />
Expand All @@ -129,6 +130,7 @@
<Compile Include="Handlers\ManagedZStackHandler.cs" />
<Compile Include="Handlers\ManagedHStackHandler.cs" />
<Compile Include="Handlers\ProgressBarHandler.cs" />
<Compile Include="Handlers\ShapeViewHandler.cs" />
<Compile Include="Handlers\SpacerHandler.cs" />
<Compile Include="Handlers\ToggleHandler.cs" />
<Compile Include="Handlers\ManagedVStackHandler.cs" />
Expand Down
1 change: 0 additions & 1 deletion src/HotUI.UWP/HotUIView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using HotUI.UWP.Handlers;
using WGrid = Windows.UI.Xaml.Controls.Grid;

Expand Down
1 change: 1 addition & 0 deletions src/HotUI.UWP/UI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static void Init()
Registrar.Handlers.Register<TextField, TextFieldHandler>();
Registrar.Handlers.Register<Toggle, ToggleHandler>();
Registrar.Handlers.Register<ProgressBar, ProgressBarHandler>();
Registrar.Handlers.Register<ShapeView, ShapeViewHandler>();
//Registrar.Handlers.Register<WebView, WebViewHandler> ();

// Containers
Expand Down
21 changes: 21 additions & 0 deletions src/HotUI/Graphics/GraphicsOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,5 +465,26 @@ public static PointF GetOppositePoint(PointF pivot, PointF oppositePoint)
var dy = oppositePoint.Y - pivot.Y;
return new PointF(pivot.X - dx, pivot.Y - dy);
}

public static PointF PolarToPoint(float aAngleInRadians, float fx, float fy)
{
var sin = (float)Math.Sin(aAngleInRadians);
var cos = (float)Math.Cos(aAngleInRadians);
return new PointF(fx * cos, fy * sin);
}

public static PointF OvalAngleToPoint(float x, float y, float width, float height, float aAngleInDegrees)
{
float vAngle = DegreesToRadians(aAngleInDegrees);

float cx = x + width / 2;
float cy = y + height / 2;

PointF vPoint = PolarToPoint(vAngle, width / 2, height / 2);

vPoint.X += cx;
vPoint.Y += cy;
return vPoint;
}
}
}

0 comments on commit 851d1b4

Please sign in to comment.