-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMultiTr.cs
197 lines (164 loc) · 6.97 KB
/
MultiTr.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
using Avalonia;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.XamlIl.Runtime;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
namespace CodingSeb.Localization.Avalonia
{
/// <summary>
/// Allow to Concatenate Multiple Tr Results with a string.Format or a separator.
/// </summary>
public class MultiTr : MarkupExtension
{
#region Constructors and args Management
public MultiTr()
{ }
public MultiTr(object arg1, object arg2)
{
ManageArg(new List<object> { arg1, arg2 });
}
public MultiTr(object arg1, object arg2, object arg3)
{
ManageArg(new List<object> { arg1, arg2, arg3 });
}
public MultiTr(object arg1, object arg2, object arg3, object arg4)
{
ManageArg(new List<object> { arg1, arg2, arg3, arg4 });
}
public MultiTr(object arg1, object arg2, object arg3, object arg4, object arg5)
{
ManageArg(new List<object> { arg1, arg2, arg3, arg4, arg5 });
}
public MultiTr(object arg1, object arg2, object arg3, object arg4, object arg5, object arg6)
{
ManageArg(new List<object> { arg1, arg2, arg3, arg4, arg5, arg6 });
}
public MultiTr(object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7)
{
ManageArg(new List<object> { arg1, arg2, arg3, arg4, arg5, arg6, arg7 });
}
public MultiTr(object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8)
{
ManageArg(new List<object> { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 });
}
private void ManageArg(List<object> args)
{
args.ForEach(arg =>
{
if (arg is Tr tr)
Collection.Add(tr);
else
Collection.Add(new Tr(arg));
});
}
#endregion
/// <summary>
/// To specify the way translations are concatenate
/// </summary>
public string StringFormat { get; set; }
/// <summary>
/// A separator text to concat between each translations
/// Used if StringFormat is not set.
/// </summary>
public string Separator { get; set; } = " ";
/// <summary>
/// A collection of sub translations to concatenate
/// </summary>
public Collection<Tr> Collection { get; } = new Collection<Tr>();
/// <summary>
/// Converter to apply on the result text
/// </summary>
public IValueConverter Converter { get; set; }
/// <summary>
/// The parameter to pass to the converter
/// </summary>
public object ConverterParameter { get; set; }
/// <summary>
/// The culture to pass to the converter
/// </summary>
public CultureInfo ConverterCulture { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget service)
{
return this;
}
IEnumerable<object> providedValues = Collection.Select(tr => tr.ProvideValue(serviceProvider, true) as IBinding ?? (object)tr);
if (providedValues.All(p => p is IBinding))
{
var internalConverter = new ForMultiTrMarkupInternalStringFormatMultiValuesConverter()
{
StringFormat = StringFormat ?? string.Join(Separator, Enumerable.Range(0, Collection.Count).Select(i => "{" + i.ToString() + "}")),
MultiTrConverter = Converter,
MultiTrConverterParameter = ConverterParameter,
MultiTrConverterCulture = ConverterCulture,
};
MultiBinding multiBinding = new()
{
Converter = internalConverter
};
Collection.ToList().ForEach(tr =>
{
IBinding bindingBase = tr.ProvideValue(serviceProvider, true) as IBinding;
if (bindingBase is MultiBinding trMultiBinding)
{
trMultiBinding.Bindings.ToList().ForEach(multiBinding.Bindings.Add);
}
else
{
multiBinding.Bindings.Add(bindingBase);
}
internalConverter.StringFormatBindings.Add(bindingBase);
});
if (service.TargetObject is not AvaloniaObject dependencyObject || service.TargetProperty is not AvaloniaProperty dependencyProperty)
{
return multiBinding;
}
else
{
dependencyObject.Bind(dependencyProperty, multiBinding, dependencyObject);
return "";
}
}
else
{
return this;
}
}
protected class ForMultiTrMarkupInternalStringFormatMultiValuesConverter : IMultiValueConverter
{
internal string StringFormat { get; set; }
internal List<IBinding> StringFormatBindings { get; } = new();
internal IValueConverter MultiTrConverter { get; set; }
internal object MultiTrConverterParameter { get; set; }
internal CultureInfo MultiTrConverterCulture { get; set; }
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{
List<object> stringFormatValues = new();
int offset = 0;
StringFormatBindings.ForEach(bindingBase =>
{
if (bindingBase is MultiBinding multiBinding)
{
stringFormatValues.Add(multiBinding.Converter.Convert(values.Skip(offset).Take(multiBinding.Bindings.Count).ToArray(), null, multiBinding.ConverterParameter, MultiTrConverterCulture));
offset += multiBinding.Bindings.Count;
}
else
{
stringFormatValues.Add(values[offset]);
offset++;
}
});
var result = string.Format(StringFormat, stringFormatValues.ToArray());
return MultiTrConverter == null ? result : MultiTrConverter.Convert(result, null, MultiTrConverterParameter, MultiTrConverterCulture);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
}
}
}