Skip to content

Commit 48b1f54

Browse files
committed
Updated InfiniteCanvas to use new .Net JsonSerializer.
1 parent 467b173 commit 48b1f54

File tree

9 files changed

+307
-31
lines changed

9 files changed

+307
-31
lines changed

Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Controls/InfiniteCanvasVirtualDrawingSurface.Render.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,21 @@ internal void ClearAll(Rect viewPort)
7878
internal string GetSerializedList()
7979
{
8080
var exportModel = new InkCanvasExportModel { DrawableList = _drawableList, Version = 1 };
81-
return JsonSerializer.Serialize(exportModel, new JsonSerializerOptions
81+
return JsonSerializer.Serialize(exportModel, GetJsonSerializerOptions());
82+
}
83+
84+
private JsonSerializerOptions GetJsonSerializerOptions()
85+
{
86+
var jsonSerializerOptions = new JsonSerializerOptions
8287
{
83-
// TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto
84-
WriteIndented = true,
85-
});
88+
WriteIndented = true
89+
};
90+
91+
// This will be needed until These two issues are fixed:
92+
// https://github.com/dotnet/runtime/issues/30083
93+
// https://github.com/dotnet/runtime/issues/29937
94+
jsonSerializerOptions.Converters.Add(new IDrawableConverter());
95+
return jsonSerializerOptions;
8696
}
8797

8898
internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom)
@@ -97,17 +107,11 @@ internal void RenderFromJsonAndDraw(Rect viewPort, string json, float zoom)
97107
if (token.RootElement.ValueKind == JsonValueKind.Array)
98108
{
99109
// first sin, because of creating a file without versioning so we have to be able to import without breaking changes.
100-
newList = JsonSerializer.Deserialize<List<IDrawable>>(json, new JsonSerializerOptions
101-
{
102-
// TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto
103-
});
110+
newList = JsonSerializer.Deserialize<List<IDrawable>>(json, GetJsonSerializerOptions());
104111
}
105112
else
106113
{
107-
newList = JsonSerializer.Deserialize<InkCanvasExportModel>(json, new JsonSerializerOptions
108-
{
109-
// TODO: Is this supported? -> TypeNameHandling = TypeNameHandling.Auto
110-
}).DrawableList;
114+
newList = JsonSerializer.Deserialize<InkCanvasExportModel>(json, GetJsonSerializerOptions()).DrawableList;
111115
}
112116

113117
foreach (var drawable in newList)

Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/IDrawable.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Text.Json;
56
using Microsoft.Graphics.Canvas;
67
using Windows.Foundation;
78

@@ -13,6 +14,12 @@ internal interface IDrawable
1314

1415
bool IsVisible(Rect viewPort);
1516

17+
void WriteJson(Utf8JsonWriter writer);
18+
19+
void ReadProperty(string propertyName, ref Utf8JsonReader reader);
20+
21+
void OnDeserialized();
22+
1623
bool IsActive { get; set; }
1724

1825
Rect Bounds { get; set; }

Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/InkDrawable.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Linq;
8-
using System.Runtime.Serialization;
8+
using System.Text.Json;
99
using System.Text.Json.Serialization;
1010
using Microsoft.Graphics.Canvas;
1111
using Windows.Foundation;
@@ -19,6 +19,9 @@ internal class InkDrawable : IDrawable
1919
[JsonIgnore]
2020
public IReadOnlyList<InkStroke> Strokes { get; set; }
2121

22+
[JsonPropertyName("$type")]
23+
public string Type => IDrawableConverter.GetDiscriminator(GetType());
24+
2225
public List<SerializableStroke> SerializableStrokeList { get; set; }
2326

2427
public Rect Bounds { get; set; }
@@ -27,6 +30,10 @@ internal class InkDrawable : IDrawable
2730

2831
internal static readonly InkStrokeBuilder StrokeBuilder = new InkStrokeBuilder();
2932

33+
public InkDrawable()
34+
{
35+
}
36+
3037
public InkDrawable(IReadOnlyList<InkStroke> strokes)
3138
{
3239
if (strokes == null || !strokes.Any())
@@ -83,8 +90,7 @@ private static InkPoint MapPointToToSessionBounds(InkPoint point, Rect sessionBo
8390
return new InkPoint(new Point(point.Position.X - sessionBounds.X, point.Position.Y - sessionBounds.Y), point.Pressure, point.TiltX, point.TiltY, point.Timestamp);
8491
}
8592

86-
[OnSerializing]
87-
internal void OnSerializingMethod(StreamingContext context)
93+
public void WriteJson(Utf8JsonWriter writer)
8894
{
8995
SerializableStrokeList = new List<SerializableStroke>(Strokes.Count);
9096
foreach (var stroke in Strokes)
@@ -103,10 +109,15 @@ internal void OnSerializingMethod(StreamingContext context)
103109
serializableStroke.PointTransform = stroke.PointTransform;
104110
SerializableStrokeList.Add(serializableStroke);
105111
}
112+
113+
var options = new JsonSerializerOptions();
114+
options.Converters.Add(new SerializableStrokeConverter());
115+
JsonSerializer.Serialize(writer, this, options);
116+
117+
SerializableStrokeList = null;
106118
}
107119

108-
[OnDeserialized]
109-
internal void OnDeserializedMethod(StreamingContext context)
120+
public void OnDeserialized()
110121
{
111122
var finalStrokeList = new List<InkStroke>(SerializableStrokeList.Count);
112123

@@ -121,10 +132,18 @@ internal void OnDeserializedMethod(StreamingContext context)
121132
SerializableStrokeList = null;
122133
}
123134

124-
[OnSerialized]
125-
internal void OnSerializedMethod(StreamingContext context)
135+
public void ReadProperty(string propertyName, ref Utf8JsonReader reader)
126136
{
127-
SerializableStrokeList = null;
137+
switch (propertyName)
138+
{
139+
case "SerializableStrokeList":
140+
var options = new JsonSerializerOptions();
141+
options.Converters.Add(new SerializableStrokeConverter());
142+
SerializableStrokeList = JsonSerializer.Deserialize<List<SerializableStroke>>(ref reader, options);
143+
break;
144+
default:
145+
break;
146+
}
128147
}
129148
}
130149
}

Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/Drawables/TextDrawable.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Text.Json;
6+
using System.Text.Json.Serialization;
57
using Microsoft.Graphics.Canvas;
68
using Microsoft.Graphics.Canvas.Text;
79
using Windows.Foundation;
@@ -13,6 +15,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
1315
{
1416
internal class TextDrawable : IDrawable
1517
{
18+
[JsonPropertyName("$type")]
19+
public string Type => IDrawableConverter.GetDiscriminator(GetType());
20+
1621
public string Text { get; set; }
1722

1823
public Rect Bounds { get; set; }
@@ -27,6 +32,10 @@ internal class TextDrawable : IDrawable
2732

2833
public bool IsItalic { get; set; }
2934

35+
public TextDrawable()
36+
{
37+
}
38+
3039
public TextDrawable(double left, double top, double width, double height, float fontSize, string text, Color textColor, bool isBold, bool isItalic)
3140
{
3241
Bounds = new Rect(left, top, width, height);
@@ -76,5 +85,38 @@ public float HorizontalMarginBasedOnFont
7685
return ((100 - FontSize) / 10) + 5;
7786
}
7887
}
88+
89+
public void WriteJson(Utf8JsonWriter writer)
90+
{
91+
JsonSerializer.Serialize(writer, this);
92+
}
93+
94+
public void OnDeserialized()
95+
{
96+
}
97+
98+
public void ReadProperty(string propertyName, ref Utf8JsonReader reader)
99+
{
100+
switch (propertyName)
101+
{
102+
case "Text":
103+
Text = reader.GetString();
104+
break;
105+
case "FontSize":
106+
FontSize = reader.GetSingle();
107+
break;
108+
case "TextColor":
109+
TextColor = JsonSerializer.Deserialize<Color>(ref reader);
110+
break;
111+
case "IsBold":
112+
IsBold = reader.GetBoolean();
113+
break;
114+
case "IsItalic":
115+
IsItalic = reader.GetBoolean();
116+
break;
117+
default:
118+
break;
119+
}
120+
}
79121
}
80122
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
8+
using Windows.Foundation;
9+
10+
namespace Microsoft.Toolkit.Uwp.UI.Controls
11+
{
12+
internal class IDrawableConverter : JsonConverter<IDrawable>
13+
{
14+
public IDrawableConverter()
15+
{
16+
}
17+
18+
public override bool CanConvert(Type typeToConvert) => typeof(IDrawable).IsAssignableFrom(typeToConvert);
19+
20+
public override IDrawable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
21+
{
22+
if (reader.TokenType != JsonTokenType.StartObject)
23+
{
24+
throw new JsonException();
25+
}
26+
27+
reader.Read();
28+
if (reader.TokenType != JsonTokenType.PropertyName)
29+
{
30+
throw new JsonException();
31+
}
32+
33+
string propertyName = reader.GetString();
34+
if (propertyName != "$type")
35+
{
36+
throw new JsonException();
37+
}
38+
39+
reader.Read();
40+
if (reader.TokenType != JsonTokenType.String)
41+
{
42+
throw new JsonException();
43+
}
44+
45+
var typeDiscriminator = reader.GetString();
46+
IDrawable drawable;
47+
if (typeDiscriminator == GetDiscriminator(typeof(InkDrawable)))
48+
{
49+
drawable = new InkDrawable();
50+
}
51+
else if (typeDiscriminator == GetDiscriminator(typeof(TextDrawable)))
52+
{
53+
drawable = new TextDrawable();
54+
}
55+
else
56+
{
57+
throw new JsonException();
58+
}
59+
60+
while (reader.Read())
61+
{
62+
if (reader.TokenType == JsonTokenType.EndObject)
63+
{
64+
drawable.OnDeserialized();
65+
return drawable;
66+
}
67+
68+
if (reader.TokenType == JsonTokenType.PropertyName)
69+
{
70+
propertyName = reader.GetString();
71+
reader.Read();
72+
switch (propertyName)
73+
{
74+
case "IsActive":
75+
drawable.IsActive = reader.GetBoolean();
76+
break;
77+
case "Bounds":
78+
drawable.Bounds = JsonSerializer.Deserialize<Rect>(ref reader);
79+
break;
80+
default:
81+
drawable.ReadProperty(propertyName, ref reader);
82+
break;
83+
}
84+
}
85+
}
86+
87+
throw new JsonException();
88+
}
89+
90+
public override void Write(Utf8JsonWriter writer, IDrawable drawable, JsonSerializerOptions options)
91+
{
92+
drawable.WriteJson(writer);
93+
}
94+
95+
internal static string GetDiscriminator(Type type)
96+
{
97+
return $"{type.FullName}, {type.Assembly.GetName().Name}";
98+
}
99+
}
100+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Numerics;
7+
using System.Text.Json;
8+
using System.Text.Json.Serialization;
9+
10+
namespace Microsoft.Toolkit.Uwp.UI.Controls
11+
{
12+
internal class Matrix3x2Converter : JsonConverter<Matrix3x2>
13+
{
14+
public override Matrix3x2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
15+
{
16+
if (reader.TokenType != JsonTokenType.StartObject)
17+
{
18+
throw new JsonException();
19+
}
20+
21+
string propertyName;
22+
Matrix3x2 matrix = default;
23+
24+
while (reader.Read())
25+
{
26+
if (reader.TokenType == JsonTokenType.EndObject)
27+
{
28+
return matrix;
29+
}
30+
31+
if (reader.TokenType == JsonTokenType.PropertyName)
32+
{
33+
propertyName = reader.GetString();
34+
reader.Read();
35+
switch (propertyName)
36+
{
37+
case "M11":
38+
matrix.M11 = reader.GetSingle();
39+
break;
40+
case "M12":
41+
matrix.M12 = reader.GetSingle();
42+
break;
43+
case "M21":
44+
matrix.M21 = reader.GetSingle();
45+
break;
46+
case "M22":
47+
matrix.M22 = reader.GetSingle();
48+
break;
49+
case "M31":
50+
matrix.M31 = reader.GetSingle();
51+
break;
52+
case "M32":
53+
matrix.M32 = reader.GetSingle();
54+
break;
55+
}
56+
}
57+
}
58+
59+
throw new JsonException();
60+
}
61+
62+
public override void Write(Utf8JsonWriter writer, Matrix3x2 value, JsonSerializerOptions options)
63+
{
64+
writer.WriteStartObject();
65+
66+
writer.WriteNumber("M11", value.M11);
67+
writer.WriteNumber("M12", value.M12);
68+
writer.WriteNumber("M21", value.M21);
69+
writer.WriteNumber("M22", value.M22);
70+
writer.WriteNumber("M31", value.M31);
71+
writer.WriteNumber("M32", value.M32);
72+
73+
writer.WriteEndObject();
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)