Skip to content

Commit

Permalink
refactor: avoid using setters in Node
Browse files Browse the repository at this point in the history
  • Loading branch information
yuto-trd committed Oct 31, 2024
1 parent a44bbb4 commit 21edab0
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 236 deletions.
60 changes: 40 additions & 20 deletions src/Beutl.Engine/Styling/StyleSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ namespace Beutl.Styling;
public static class StyleSerializer
{
public static ISetter? ToSetter(this JsonNode? json, string name, Type targetType, ICoreSerializationContext context)
{
var (property, value, animation) = ToTuple(json, name, targetType, context);
if (property is null)
return null;

var helper = (IGenericHelper)typeof(GenericHelper<>)
.MakeGenericType(property.PropertyType)!
.GetField("Instance")!
.GetValue(null)!;

return helper.InitializeSetter(property, value, animation);
}

public static (CoreProperty? property, Optional<object?> value, IAnimation? animation) ToTuple(JsonNode? json, string name, Type targetType, ICoreSerializationContext context)
{
JsonNode? animationNode = null;
JsonNode? valueNode = null;
Expand All @@ -26,13 +40,13 @@ public static class StyleSerializer
&& ownerNode is JsonValue ownerValue
&& ownerValue.TryGetValue(out string? ownerStr))
{
if (TypeFormat.ToType(ownerStr) is Type ownerType1)
if (TypeFormat.ToType(ownerStr) is { } ownerType1)
{
ownerType = ownerType1;
}
else
{
return null;
return default;
}
}

Expand All @@ -46,12 +60,7 @@ public static class StyleSerializer
CoreProperty? property = PropertyRegistry.GetRegistered(ownerType).FirstOrDefault(x => x.Name == name);

if (property == null)
return null;

var helper = (IGenericHelper)typeof(GenericHelper<>)
.MakeGenericType(property.PropertyType)
.GetField("Instance")!
.GetValue(null)!;
return default;

Optional<object?> value = null;
if (valueNode != null)
Expand All @@ -69,18 +78,29 @@ public static class StyleSerializer
}
}

return helper.InitializeSetter(property, value, animationNode?.ToAnimation(property, context));
return (property, value, animationNode?.ToAnimation(property, context));
}

public static (string, JsonNode?) ToJson(this ISetter setter, Type targetType, ICoreSerializationContext context)
{
return ToJson(
setter.Property,
setter.Value,
setter.Animation,
targetType,
context
);
}

public static (string, JsonNode?) ToJson(CoreProperty property, object? value, IAnimation? animation, Type targetType, ICoreSerializationContext context)
{
string? owner = null;
JsonNode? animationNode = null;
string? name = setter.Property.Name;
string? name = property.Name;

if (!targetType.IsAssignableTo(setter.Property.OwnerType))
if (!targetType.IsAssignableTo(property.OwnerType))
{
owner = TypeFormat.ToString(setter.Property.OwnerType);
owner = TypeFormat.ToString(property.OwnerType);
}

// Todo: 互換性維持のために汚くなってる
Expand All @@ -89,36 +109,36 @@ public static (string, JsonNode?) ToJson(this ISetter setter, Type targetType, I
var innerContext = new JsonSerializationContext(targetType, errorNotifier, context, simJson);
using (ThreadLocalSerializationContext.Enter(innerContext))
{
setter.Property.RouteSerialize(innerContext, setter.Value);
property.RouteSerialize(innerContext, value);
}
JsonNode? value = simJson[name];
JsonNode? jsonNode = simJson[name];
simJson[name] = null;

if (setter.Animation is { } animation)
if (animation is not null)
{
if (animation.Property != setter.Property)
if (animation.Property.Id != property.Id)
{
throw new InvalidOperationException("Setter.Animation.Property != Setter.Property");
throw new InvalidOperationException("Animation.Property != Property");
}

animationNode = animation.ToJson(innerContext);
}

if (value is JsonValue jsonValue
if (jsonNode is JsonValue jsonValue
&& owner == null
&& animationNode == null)
{
return (name, jsonValue);
}
else if (value == null && owner == null && animationNode == null)
else if (jsonNode == null && owner == null && animationNode == null)
{
return (name, null);
}
else
{
var json = new JsonObject
{
["Value"] = value
["Value"] = jsonNode
};

if (owner != null)
Expand Down
42 changes: 42 additions & 0 deletions src/Beutl.ProjectSystem/NodeTree/DefaultInputSocket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Beutl.Media;
using Beutl.Serialization;

namespace Beutl.NodeTree;

public sealed class DefaultInputSocket<T> : InputSocket<T>, IDefaultInputSocket
{
public void SetPropertyAdapter(NodePropertyAdapter<T> property)
{
Property = property;
property.Invalidated += OnAdapterInvalidated;
}

void IDefaultInputSocket.SetPropertyAdapter(object property)
{
var obj = (NodePropertyAdapter<T>)property;
Property = obj;
obj.Invalidated += OnAdapterInvalidated;
}

private void OnAdapterInvalidated(object? sender, EventArgs e)
{
RaiseInvalidated(new RenderInvalidatedEventArgs(this));
}

public NodePropertyAdapter<T>? GetProperty()
{
return Property as NodePropertyAdapter<T>;
}

public override void Serialize(ICoreSerializationContext context)
{
base.Serialize(context);
GetProperty()?.Serialize(context);
}

public override void Deserialize(ICoreSerializationContext context)
{
base.Deserialize(context);
GetProperty()?.Deserialize(context);
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
using System.Text.Json.Nodes;

using Beutl.Media;
using Beutl.Media;
using Beutl.Serialization;

namespace Beutl.NodeTree;

public sealed class NodeItemForSetter<T> : NodeItem<T>
public sealed class DefaultNodeItem<T> : NodeItem<T>
{
public void SetProperty(SetterAdapter<T> property)
public void SetProperty(NodePropertyAdapter<T> property)
{
Property = property;
property.Setter.Invalidated += OnSetterInvalidated;
property.Invalidated += OnAdapterInvalidated;
}

private void OnSetterInvalidated(object? sender, EventArgs e)
private void OnAdapterInvalidated(object? sender, EventArgs e)
{
RaiseInvalidated(new RenderInvalidatedEventArgs(this));
}

public SetterAdapter<T>? GetProperty()
public NodePropertyAdapter<T>? GetProperty()
{
return Property as SetterAdapter<T>;
return Property as NodePropertyAdapter<T>;
}

public override void Serialize(ICoreSerializationContext context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Beutl.NodeTree;

internal interface IInputSocketForSetter : IInputSocket
internal interface IDefaultInputSocket : IInputSocket
{
new int LocalId { get; set; }

Expand Down
44 changes: 0 additions & 44 deletions src/Beutl.ProjectSystem/NodeTree/InputSocketForSetter.cs

This file was deleted.

42 changes: 19 additions & 23 deletions src/Beutl.ProjectSystem/NodeTree/Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,8 @@ protected InputSocket<T> CreateInput<T>(CoreProperty<T> property, int localId =
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property);
var adapter = new SetterAdapter<T>(setter, property.OwnerType);
var socket = new InputSocketForSetter<T>() { LocalId = localId };
var adapter = new NodePropertyAdapter<T>(property, property.OwnerType);
var socket = new DefaultInputSocket<T> { LocalId = localId };
socket.SetPropertyAdapter(adapter);
return socket;
}
Expand All @@ -240,9 +239,8 @@ protected IInputSocket CreateInput(CoreProperty property, int localId = -1)
throw new InvalidOperationException("An item with the same local-id already exists.");

Type propertyType = property.PropertyType;
object setter = Activator.CreateInstance(typeof(Setter<>).MakeGenericType(propertyType), property)!;
object adapter = Activator.CreateInstance(typeof(SetterAdapter<>).MakeGenericType(propertyType), setter, property.OwnerType)!;
var socket = (IInputSocketForSetter)Activator.CreateInstance(typeof(InputSocketForSetter<>).MakeGenericType(propertyType))!;
object adapter = Activator.CreateInstance(typeof(NodePropertyAdapter<>).MakeGenericType(propertyType), property, property.OwnerType)!;
var socket = (IDefaultInputSocket)Activator.CreateInstance(typeof(DefaultInputSocket<>).MakeGenericType(propertyType))!;
socket.LocalId = localId;
socket.SetPropertyAdapter(adapter);
return socket;
Expand All @@ -255,9 +253,8 @@ protected InputSocket<T> CreateInput<T, TOwner>(CoreProperty<T> property, int lo
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property);
var adapter = new SetterAdapter<T>(setter, typeof(TOwner));
var socket = new InputSocketForSetter<T>() { LocalId = localId };
var adapter = new NodePropertyAdapter<T>(property, typeof(TOwner));
var socket = new DefaultInputSocket<T> { LocalId = localId };
socket.SetPropertyAdapter(adapter);
return socket;
}
Expand All @@ -269,9 +266,9 @@ protected InputSocket<T> CreateInput<T>(CoreProperty<T> property, T value, int l
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property, value);
var adapter = new SetterAdapter<T>(setter, property.OwnerType);
var socket = new InputSocketForSetter<T>() { LocalId = localId };
var adapter = new NodePropertyAdapter<T>(property, property.OwnerType);
adapter.SetValue(value);
var socket = new DefaultInputSocket<T> { LocalId = localId };
socket.SetPropertyAdapter(adapter);
return socket;
}
Expand All @@ -283,9 +280,9 @@ protected InputSocket<T> CreateInput<T, TOwner>(CoreProperty<T> property, T valu
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property, value);
var adapter = new SetterAdapter<T>(setter, typeof(TOwner));
var socket = new InputSocketForSetter<T>() { LocalId = localId };
var adapter = new NodePropertyAdapter<T>(property, typeof(TOwner));
adapter.SetValue(value);
var socket = new DefaultInputSocket<T> { LocalId = localId };
socket.SetPropertyAdapter(adapter);
return socket;
}
Expand All @@ -297,7 +294,7 @@ protected InputSocket<T> CreateInput<T>(string name, int localId = -1)
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

return new InputSocketForSetter<T>()
return new DefaultInputSocket<T>
{
Name = name,
LocalId = localId
Expand All @@ -311,7 +308,7 @@ protected IInputSocket CreateInput(string name, Type type, int localId = -1)
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var socket = (IInputSocketForSetter)Activator.CreateInstance(typeof(InputSocketForSetter<>).MakeGenericType(type))!;
var socket = (IDefaultInputSocket)Activator.CreateInstance(typeof(DefaultInputSocket<>).MakeGenericType(type))!;
socket.Name = name;
socket.LocalId = localId;
return socket;
Expand Down Expand Up @@ -369,9 +366,8 @@ protected NodeItem<T> CreateProperty<T>(CoreProperty<T> property, int localId =
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property);
var adapter = new SetterAdapter<T>(setter, property.OwnerType);
var socket = new NodeItemForSetter<T>();
var adapter = new NodePropertyAdapter<T>(property, property.OwnerType);
var socket = new DefaultNodeItem<T>();
socket.SetProperty(adapter);
socket.LocalId = localId;
return socket;
Expand All @@ -384,9 +380,9 @@ protected NodeItem<T> CreateProperty<T>(CoreProperty<T> property, T value, int l
if (ValidateLocalId(localId))
throw new InvalidOperationException("An item with the same local-id already exists.");

var setter = new Setter<T>(property, value);
var adapter = new SetterAdapter<T>(setter, property.OwnerType);
var socket = new NodeItemForSetter<T>();
var adapter = new NodePropertyAdapter<T>(property, property.OwnerType);
adapter.SetValue(value);
var socket = new DefaultNodeItem<T>();
socket.SetProperty(adapter);
socket.LocalId = localId;
return socket;
Expand Down
Loading

0 comments on commit 21edab0

Please sign in to comment.