From 2d8d121afd79b6528997ef28ae044a71bf853346 Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk Date: Mon, 21 Feb 2022 22:49:54 +0200 Subject: [PATCH 1/2] Nullable fixes in DrawingView --- .../TestCases/DrawingViewInExpanderPage.xaml | 25 ++++++++++ .../DrawingViewInExpanderPage.xaml.cs | 7 +++ .../TestCases/TestCasesGalleryViewModel.cs | 5 ++ .../Renderer/DrawingViewRenderer.android.cs | 18 ++++--- .../Renderer/DrawingViewRenderer.gtk.cs | 49 ++++++++++++------- .../Renderer/DrawingViewRenderer.ios.cs | 10 ++-- .../Renderer/DrawingViewRenderer.macos.cs | 14 +++--- .../Renderer/DrawingViewRenderer.tizen.cs | 26 +++++----- .../Renderer/DrawingViewRenderer.uwp.cs | 38 +++++++++----- 9 files changed, 132 insertions(+), 60 deletions(-) create mode 100644 samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml create mode 100644 samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml.cs diff --git a/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml b/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml new file mode 100644 index 000000000..5e40359ba --- /dev/null +++ b/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml.cs b/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml.cs new file mode 100644 index 000000000..d5d7b1caa --- /dev/null +++ b/samples/XCT.Sample/Pages/TestCases/DrawingViewInExpanderPage.xaml.cs @@ -0,0 +1,7 @@ +namespace Xamarin.CommunityToolkit.Sample.Pages.TestCases +{ + public partial class DrawingViewInExpanderPage + { + public DrawingViewInExpanderPage() => InitializeComponent(); + } +} \ No newline at end of file diff --git a/samples/XCT.Sample/ViewModels/TestCases/TestCasesGalleryViewModel.cs b/samples/XCT.Sample/ViewModels/TestCases/TestCasesGalleryViewModel.cs index 923ad63ee..43a9ce311 100644 --- a/samples/XCT.Sample/ViewModels/TestCases/TestCasesGalleryViewModel.cs +++ b/samples/XCT.Sample/ViewModels/TestCases/TestCasesGalleryViewModel.cs @@ -48,6 +48,11 @@ protected override IEnumerable CreateItems() => new[] typeof(SnackBarActionExceptionPage), "SnackBar Action Exception", "Exception in SnackBar's action doesn't crash the app."), + + new SectionModel( + typeof(DrawingViewInExpanderPage), + "DrawingView in expander", + "DrawingView in Expander Page"), }; } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs index 2f9721b7b..c2ed28eca 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.android.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using Android.Content; using Android.Graphics; @@ -78,20 +79,23 @@ protected override void OnSizeChanged(int w, int h, int oldw, int oldh) base.OnSizeChanged(w, h, oldw, oldh); - canvasBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888!)!; - drawCanvas = new Canvas(canvasBitmap); - LoadLines(); + canvasBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888 ?? throw new NullReferenceException("Unable to create Bitmap config")); + if (canvasBitmap is not null) + { + drawCanvas = new Canvas(canvasBitmap); + LoadLines(); + } } protected override void OnDraw(Canvas? canvas) { base.OnDraw(canvas); - if (canvas is not null) + if (canvas is not null && canvasBitmap is not null) { Draw(Element.Lines, canvas); - canvas.DrawBitmap(canvasBitmap!, 0, 0, canvasPaint); + canvas.DrawBitmap(canvasBitmap, 0, 0, canvasPaint); canvas.DrawPath(drawPath, drawPaint); } } @@ -196,7 +200,7 @@ void LoadLines() if (drawCanvas is null) return; - drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid(), PorterDuff.Mode.Clear!); + drawCanvas.DrawColor(Element.BackgroundColor.ToAndroid()); drawPath.Reset(); var lines = Element.Lines; if (lines.Count > 0) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs index 86fcaaa16..9e9610da0 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs @@ -50,17 +50,17 @@ protected override void OnElementChanged(ElementChangedEventArgs e) SetNativeControl(vBox); } - if (e.OldElement != null) + if (e.OldElement != null && area is not null) { - area!.ExposeEvent -= OnDrawingAreaExposed; + area.ExposeEvent -= OnDrawingAreaExposed; area.ButtonPressEvent -= OnMousePress; area.ButtonReleaseEvent -= OnMouseRelease; area.MotionNotifyEvent -= OnMouseMotion; } - if (e.NewElement != null) + if (e.NewElement != null && area is not null) { - area!.ExposeEvent += OnDrawingAreaExposed; + area.ExposeEvent += OnDrawingAreaExposed; area.ButtonPressEvent += OnMousePress; area.ButtonReleaseEvent += OnMouseRelease; area.MotionNotifyEvent += OnMouseMotion; @@ -82,8 +82,13 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE void OnDrawingAreaExposed(object source, ExposeEventArgs args) { + if (area is null) + { + return; + } + Context ctx; - using (ctx = CairoHelper.Create(area!.GdkWindow)) + using (ctx = CairoHelper.Create(area.GdkWindow)) { ctx.SetSource(new SurfacePattern(surface)); ctx.Paint(); @@ -111,7 +116,7 @@ void OnMousePress(object source, ButtonPressEventArgs args) }; previousPoint = point; isDrawing = true; - area!.QueueDraw(); + area?.QueueDraw(); if (!Element.MultiLineMode) Element.Lines.Clear(); } @@ -125,7 +130,7 @@ void OnMouseRelease(object source, ButtonReleaseEventArgs args) using var ctx = new Context(surface); DrawPoint(ctx, point); - area!.QueueDraw(); + area?.QueueDraw(); if (currentLine != null) { Element.Lines.Add(currentLine); @@ -146,19 +151,23 @@ void OnMouseMotion(object source, MotionNotifyEventArgs args) using var ctx = new Context(surface); DrawPoint(ctx, point); - area!.QueueDraw(); + area?.QueueDraw(); } } void DrawPoint(Context ctx, PointD pointD) { - ctx.SetSourceRGBA(currentLine!.LineColor.R, currentLine!.LineColor.G, currentLine!.LineColor.B, currentLine!.LineColor.A); - ctx.LineWidth = currentLine.LineWidth; + if (currentLine is not null) + { + ctx.SetSourceRGBA(currentLine.LineColor.R, currentLine.LineColor.G, currentLine.LineColor.B, currentLine.LineColor.A); + ctx.LineWidth = currentLine.LineWidth; + } + ctx.MoveTo(previousPoint); previousPoint = pointD; ctx.LineTo(pointD); ctx.Stroke(); - currentLine.Points.Add(new Point(pointD.X, pointD.Y)); + currentLine?.Points.Add(new Point(pointD.X, pointD.Y)); } void LoadPoints(ImageSurface imageSurface) @@ -177,7 +186,7 @@ void LoadPoints(ImageSurface imageSurface) foreach (var stylusPoint in stylusPoints) DrawPoint(ctx, stylusPoint); - area!.QueueDraw(); + area?.QueueDraw(); } } } @@ -190,12 +199,16 @@ protected override void Dispose(bool disposing) if (disposing) { - area!.ExposeEvent -= OnDrawingAreaExposed; - area.ButtonPressEvent -= OnMousePress; - area.ButtonReleaseEvent -= OnMouseRelease; - area.MotionNotifyEvent -= OnMouseMotion; - area.Dispose(); - surface!.Dispose(); + if (area is not null) + { + area.ExposeEvent -= OnDrawingAreaExposed; + area.ButtonPressEvent -= OnMousePress; + area.ButtonReleaseEvent -= OnMouseRelease; + area.MotionNotifyEvent -= OnMouseMotion; + area.Dispose(); + } + + surface?.Dispose(); if (Element != null) Element.Lines.CollectionChanged -= OnLinesCollectionChanged; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.ios.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.ios.cs index afe50b0ae..42c8bfd6a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.ios.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.ios.cs @@ -18,8 +18,8 @@ namespace Xamarin.CommunityToolkit.UI.Views /// public class DrawingViewRenderer : ViewRenderer { + readonly UIBezierPath currentPath; bool disposed; - UIBezierPath currentPath; UIColor? lineColor; CGPoint previousPoint; Line? currentLine; @@ -61,11 +61,11 @@ public override void TouchesBegan(NSSet touches, UIEvent? evt) var touch = (UITouch)touches.AnyObject; previousPoint = touch.PreviousLocationInView(this); currentPath.MoveTo(previousPoint); - currentLine = new Line() + currentLine = new Line { - Points = new ObservableCollection() + Points = new ObservableCollection { - new Point(previousPoint.X, previousPoint.Y) + new (previousPoint.X, previousPoint.Y) } }; @@ -105,7 +105,7 @@ public override void TouchesCancelled(NSSet touches, UIEvent? evt) public override void Draw(CGRect rect) { - lineColor!.SetStroke(); + lineColor?.SetStroke(); currentPath.Stroke(); } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.macos.cs index 78d79eb4a..d1240fbe8 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.macos.cs @@ -17,8 +17,8 @@ namespace Xamarin.CommunityToolkit.UI.Views /// public class DrawingViewRenderer : ViewRenderer { + readonly NSBezierPath currentPath; bool disposed; - NSBezierPath currentPath; NSColor? lineColor; CGPoint previousPoint; Line? currentLine; @@ -58,11 +58,11 @@ public override void MouseDown(NSEvent theEvent) previousPoint = theEvent.LocationInWindow; currentPath.MoveTo(previousPoint); - currentLine = new Line() + currentLine = new Line { - Points = new ObservableCollection() + Points = new ObservableCollection { - new Point(previousPoint.X, previousPoint.Y) + new (previousPoint.X, previousPoint.Y) } }; @@ -94,7 +94,7 @@ public override void MouseDragged(NSEvent theEvent) public override void DrawRect(CGRect dirtyRect) { base.DrawRect(dirtyRect); - lineColor!.SetStroke(); + lineColor?.SetStroke(); currentPath.Stroke(); } @@ -124,8 +124,8 @@ void UpdatePath(Line line) Element.Lines.CollectionChanged -= OnLinesCollectionChanged; var smoothedPoints = line.EnableSmoothedPath - ? SmoothedPathWithGranularity(line.Points, line.Granularity) - : new ObservableCollection(line.Points); + ? SmoothedPathWithGranularity(line.Points, line.Granularity) + : new ObservableCollection(line.Points); line.Points.Clear(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.tizen.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.tizen.cs index 9acbeb6d0..d68bbbb34 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.tizen.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.tizen.cs @@ -36,17 +36,17 @@ protected override void OnElementChanged(ElementChangedEventArgs e) SetNativeControl(canvasView); } - if (e.OldElement != null) + if (e.OldElement != null && canvasView is not null) { - canvasView!.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseDown, MouseDown); + canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseDown, MouseDown); canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseUp, MouseUp); canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseMove, MouseMove); canvasView.PaintSurface -= OnPaintSurface; } - if (e.NewElement != null) + if (e.NewElement != null && canvasView is not null) { - canvasView!.PaintSurface += OnPaintSurface; + canvasView.PaintSurface += OnPaintSurface; canvasView.EvasCanvas.AddEventAction(EvasObjectCallbackType.MouseDown, MouseDown); canvasView.EvasCanvas.AddEventAction(EvasObjectCallbackType.MouseUp, MouseUp); canvasView.EvasCanvas.AddEventAction(EvasObjectCallbackType.MouseMove, MouseMove); @@ -56,9 +56,9 @@ protected override void OnElementChanged(ElementChangedEventArgs e) protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); - if (e.PropertyName == DrawingView.LinesProperty.PropertyName) + if (e.PropertyName == DrawingView.LinesProperty.PropertyName && canvasView is not null) { - canvasView!.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseUp, MouseUp); + canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseUp, MouseUp); LoadPoints(); canvasView.EvasCanvas.AddEventAction(EvasObjectCallbackType.MouseUp, MouseUp); } @@ -68,10 +68,10 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE void MouseMove() { - if (isDrawing) + if (isDrawing && canvasView is not null) { - var point = canvasView!.EvasCanvas.Pointer; - currentLine!.Points.Add(new Point(point.X, point.Y)); + var point = canvasView.EvasCanvas.Pointer; + currentLine?.Points.Add(new Point(point.X, point.Y)); canvasView.Invalidate(); } } @@ -111,7 +111,7 @@ void LoadPoints() if (Element == null) return; - canvasView!.Invalidate(); + canvasView?.Invalidate(); } void DrawPath(SKCanvas canvas) @@ -150,7 +150,11 @@ protected override void Dispose(bool disposing) if (Element != null) { Element.Lines.CollectionChanged -= OnLinesCollectionChanged; - canvasView!.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseDown, MouseDown); + } + + if (canvasView is not null) + { + canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseDown, MouseDown); canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseUp, MouseUp); canvasView.EvasCanvas.DeleteEventAction(EvasObjectCallbackType.MouseMove, MouseMove); canvasView.PaintSurface -= OnPaintSurface; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.uwp.cs index feb400d5e..75f6f4451 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.uwp.cs @@ -42,24 +42,31 @@ protected override void OnElementChanged(ElementChangedEventArgs e) Element.Lines.CollectionChanged += OnCollectionChanged; SetNativeControl(canvas); - canvas!.InkPresenter.StrokeInput.StrokeStarted += StrokeInput_StrokeStarted; + canvas.InkPresenter.StrokeInput.StrokeStarted += StrokeInput_StrokeStarted; canvas.InkPresenter.StrokesCollected += OnInkPresenterStrokesCollected; } if (e.OldElement != null) { - canvas!.InkPresenter.StrokeInput.StrokeStarted -= StrokeInput_StrokeStarted; - canvas.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; - Element!.Lines.CollectionChanged -= OnCollectionChanged; + if (canvas is not null) + { + canvas.InkPresenter.StrokeInput.StrokeStarted -= StrokeInput_StrokeStarted; + canvas.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; + } + + if (Element is not null) + { + Element.Lines.CollectionChanged -= OnCollectionChanged; + } } } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); - if (e.PropertyName == DrawingView.LinesProperty.PropertyName) + if (e.PropertyName == DrawingView.LinesProperty.PropertyName && canvas is not null) { - canvas!.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; + canvas.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; canvas.InkPresenter.StrokeContainer.Clear(); LoadLines(); canvas.InkPresenter.StrokesCollected += OnInkPresenterStrokesCollected; @@ -111,10 +118,13 @@ void OnInkPresenterStrokesCollected(InkPresenter sender, InkStrokesCollectedEven void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args) { - canvas!.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; - canvas.InkPresenter.StrokeContainer.Clear(); - LoadLines(); - canvas.InkPresenter.StrokesCollected += OnInkPresenterStrokesCollected; + if (canvas is not null) + { + canvas.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; + canvas.InkPresenter.StrokeContainer.Clear(); + LoadLines(); + canvas.InkPresenter.StrokesCollected += OnInkPresenterStrokesCollected; + } } void LoadLines() @@ -152,7 +162,11 @@ protected override void Dispose(bool disposing) if (Element != null) { Element.Lines.CollectionChanged -= OnCollectionChanged; - canvas!.InkPresenter.StrokeInput.StrokeStarted -= StrokeInput_StrokeStarted; + } + + if (canvas is not null) + { + canvas.InkPresenter.StrokeInput.StrokeStarted -= StrokeInput_StrokeStarted; canvas.InkPresenter.StrokesCollected -= OnInkPresenterStrokesCollected; } @@ -163,7 +177,7 @@ void Clear(bool force = false) { if (!Element.MultiLineMode || force) { - canvas!.InkPresenter.StrokeContainer.Clear(); + canvas?.InkPresenter.StrokeContainer.Clear(); Element.Lines.Clear(); } } From f43d7780fd55827ed685fb4234c31a7dcca674a2 Mon Sep 17 00:00:00 2001 From: Vladislav Antonyuk <33021114+VladislavAntonyuk@users.noreply.github.com> Date: Tue, 22 Feb 2022 12:35:51 +0200 Subject: [PATCH 2/2] Update DrawingViewRenderer.gtk.cs --- .../Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs index 9e9610da0..7b420fe43 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/DrawingView/Renderer/DrawingViewRenderer.gtk.cs @@ -161,13 +161,13 @@ void DrawPoint(Context ctx, PointD pointD) { ctx.SetSourceRGBA(currentLine.LineColor.R, currentLine.LineColor.G, currentLine.LineColor.B, currentLine.LineColor.A); ctx.LineWidth = currentLine.LineWidth; + currentLine.Points.Add(new Point(pointD.X, pointD.Y)); } ctx.MoveTo(previousPoint); previousPoint = pointD; ctx.LineTo(pointD); - ctx.Stroke(); - currentLine?.Points.Add(new Point(pointD.X, pointD.Y)); + ctx.Stroke(); } void LoadPoints(ImageSurface imageSurface) @@ -218,4 +218,4 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } } -} \ No newline at end of file +}