EnumConverters.cs 12.7 KB
Newer Older
1
2
using Svg.DataTypes;
using System;
3
4
5
6
7
using System.ComponentModel;
using System.Globalization;

namespace Svg
{
8
9
    //just overrrides canconvert and returns true
    public class BaseConverter : TypeConverter
10
    {
11
        
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }
    }
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    
    public sealed class SvgBoolConverter : BaseConverter
    {
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value == null)
            {
                return true;
            }
            
            if (!(value is string))
            {
                throw new ArgumentOutOfRangeException("value must be a string.");
            }

            // Note: currently only used by SvgVisualElement.Visible but if
            // conversion is used elsewhere these checks below will need to change
            string visibility = (string)value;
            if ((visibility == "hidden") || (visibility == "collapse"))
                return false;
            else
                return true;
54
        }
55
56
        
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
57
58
59
        {
            if (destinationType == typeof(string))
            {
60
                return ((bool)value) ? "visible" : "hidden";
61
62
63
64
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }	
65
66
67
68
    }
    
    //converts enums to lower case strings
    public class EnumBaseConverter<T> : BaseConverter
69
        where T : struct
70
    {
71
72
73
74
75
76
77
78
        public enum CaseHandling
        {
            CamelCase,
            LowerCase
        }
        /// <summary> Defines if the enum literal shall be converted to lower camel case or lower case.</summary>
        public CaseHandling CaseHandlingMode { get; }

79
80
81
82
83
84
85
86
        /// <summary>If specified, upon conversion, the default value will result in 'null'.</summary>
        public T? DefaultValue { get; protected set;}

        /// <summary>Creates a new instance.</summary>
        public EnumBaseConverter() { }

        /// <summary>Creates a new instance.</summary>
        /// <param name="defaultValue">Specified the default value of the enum.</param>
87
        public EnumBaseConverter(T defaultValue, CaseHandling caseHandling = CaseHandling.CamelCase)
88
89
        {
            this.DefaultValue = defaultValue;
90
            this.CaseHandlingMode = caseHandling;
91
92
93
        }

        /// <summary>Attempts to convert the provided value to <typeparamref name="T"/>.</summary>
94
95
96
97
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value == null)
            {
98
99
100
                if (this.DefaultValue.HasValue)
                    return this.DefaultValue.Value;
                
101
102
103
104
105
106
107
108
109
                return Activator.CreateInstance(typeof(T));
            }
            
            if (!(value is string))
            {
                throw new ArgumentOutOfRangeException("value must be a string.");
            }

            return (T)Enum.Parse(typeof(T), (string)value, true);
110
        }
111
        
112
        /// <summary>Attempts to convert the value to the destination type.</summary>
113
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
114
        {
115
            if (destinationType == typeof(string) && value is T)
116
            {
117
118
119
120
121
122
                //If the value id the default value, no need to write the attribute.
                if (this.DefaultValue.HasValue && Enum.Equals(value, this.DefaultValue.Value))
                    return null;
                else
                {
                    string stringValue = ((T)value).ToString();
123
124
125
126
                    if (CaseHandlingMode == CaseHandling.LowerCase)
                    {
                        return stringValue.ToLower();
                    }
127

128
                    //most SVG attributes should be camelCase.
129
130
131
132
                    stringValue = string.Format("{0}{1}", stringValue[0].ToString().ToLower(), stringValue.Substring(1));

                    return stringValue;
                }
133
134
135
136
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }	
137
138
    }
    
139
140
    public sealed class SvgFillRuleConverter : EnumBaseConverter<SvgFillRule>
    {
141
        public SvgFillRuleConverter() : base(SvgFillRule.NonZero, CaseHandling.LowerCase) { }
142
    }
143
    
144
145
146
    public sealed class SvgColourInterpolationConverter : EnumBaseConverter<SvgColourInterpolation>
    {
        public SvgColourInterpolationConverter() : base(SvgColourInterpolation.SRGB) { }
147
148
149
150
    }
    
    public sealed class SvgClipRuleConverter : EnumBaseConverter<SvgClipRule>
    {
151
        public SvgClipRuleConverter() : base(SvgClipRule.NonZero, CaseHandling.LowerCase) { }
152
153
154
155
    }
    
    public sealed class SvgTextAnchorConverter : EnumBaseConverter<SvgTextAnchor>
    {
156
        public SvgTextAnchorConverter() : base(SvgTextAnchor.Start) { }
157
158
159
160
    }
    
    public sealed class SvgStrokeLineCapConverter : EnumBaseConverter<SvgStrokeLineCap>
    {
161
        public SvgStrokeLineCapConverter() : base(SvgStrokeLineCap.Butt) { }
162
163
164
165
    }

    public sealed class SvgStrokeLineJoinConverter : EnumBaseConverter<SvgStrokeLineJoin>
    {
166
        public SvgStrokeLineJoinConverter() : base(SvgStrokeLineJoin.Miter) { }
167
    }
168

169
170
    public sealed class SvgMarkerUnitsConverter : EnumBaseConverter<SvgMarkerUnits>
    {
171
        public SvgMarkerUnitsConverter() : base(SvgMarkerUnits.StrokeWidth) { }
172
    }
173

174
175
    public sealed class SvgFontStyleConverter : EnumBaseConverter<SvgFontStyle>
    {
176
        public SvgFontStyleConverter() : base(SvgFontStyle.All) { }
177
    }
178

179
180
    public sealed class SvgOverflowConverter : EnumBaseConverter<SvgOverflow>
    {
181
        public SvgOverflowConverter() : base(SvgOverflow.Auto) { }
182
    }
183

184
185
    public sealed class SvgTextLengthAdjustConverter : EnumBaseConverter<SvgTextLengthAdjust>
    {
186
        public SvgTextLengthAdjustConverter() : base(SvgTextLengthAdjust.Spacing) { }
187
    }
188

189
190
    public sealed class SvgTextPathMethodConverter : EnumBaseConverter<SvgTextPathMethod>
    {
191
        public SvgTextPathMethodConverter() : base(SvgTextPathMethod.Align) { }
192
    }
193

194
195
    public sealed class SvgTextPathSpacingConverter : EnumBaseConverter<SvgTextPathSpacing>
    {
196
        public SvgTextPathSpacingConverter() : base(SvgTextPathSpacing.Exact) { }
197
198
199
200
201
202
    }
    
    public sealed class SvgShapeRenderingConverter : EnumBaseConverter<SvgShapeRendering>
    {
        public SvgShapeRenderingConverter() : base(SvgShapeRendering.Inherit) { }
    }
203

204
205
206
207
208
209
210
211
212
213
    public sealed class SvgTextRenderingConverter : EnumBaseConverter<SvgTextRendering>
    {
        public SvgTextRenderingConverter() : base(SvgTextRendering.Inherit) { }
    }

    public sealed class SvgImageRenderingConverter : EnumBaseConverter<SvgImageRendering>
    {
        public SvgImageRenderingConverter() : base(SvgImageRendering.Inherit) { }
    }
    
214
215
    public sealed class SvgFontVariantConverter : EnumBaseConverter<SvgFontVariant>
    {
216
217
        public SvgFontVariantConverter() : base(SvgFontVariant.Normal) { }

218
219
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
220
221
222
            if (value.ToString() == "small-caps")
                return SvgFontVariant.Smallcaps;
            
223
224
            return base.ConvertFrom(context, culture, value);
        }
225

226
227
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
228
            if (destinationType == typeof(string) && value is SvgFontVariant && (SvgFontVariant)value == SvgFontVariant.Smallcaps)
229
230
231
            {
                return "small-caps";
            }
232
            
233
234
235
236
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

Eric Domke's avatar
Eric Domke committed
237
238
    public sealed class SvgCoordinateUnitsConverter : EnumBaseConverter<SvgCoordinateUnits>
    {
239
240
241
242
243
244
245
        //TODO Inherit is not actually valid. See TODO on SvgCoordinateUnits enum.
        public SvgCoordinateUnitsConverter() : base(SvgCoordinateUnits.Inherit) { }
    }

    public sealed class SvgGradientSpreadMethodConverter : EnumBaseConverter<SvgGradientSpreadMethod>
    {
        public SvgGradientSpreadMethodConverter() : base(SvgGradientSpreadMethod.Pad) { }
Eric Domke's avatar
Eric Domke committed
246
247
    }

Eric Domke's avatar
Eric Domke committed
248
249
    public sealed class SvgTextDecorationConverter : EnumBaseConverter<SvgTextDecoration>
    {
250
251
        public SvgTextDecorationConverter() : base(SvgTextDecoration.None) { }

Eric Domke's avatar
Eric Domke committed
252
253
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
254
255
256
            if (value.ToString() == "line-through") 
                return SvgTextDecoration.LineThrough;
            
Eric Domke's avatar
Eric Domke committed
257
258
            return base.ConvertFrom(context, culture, value);
        }
259

Eric Domke's avatar
Eric Domke committed
260
261
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
262
            if (destinationType == typeof(string) && value is SvgTextDecoration && (SvgTextDecoration)value == SvgTextDecoration.LineThrough)
Eric Domke's avatar
Eric Domke committed
263
264
265
            {
                return "line-through";
            }
266

Eric Domke's avatar
Eric Domke committed
267
268
269
270
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

271
272
    public sealed class SvgFontWeightConverter : EnumBaseConverter<SvgFontWeight>
    {
273
274
275
        //TODO Defaulting to Normal although it should be All if this is used on a font face.
        public SvgFontWeightConverter() : base(SvgFontWeight.Normal) { }

276
277
278
279
280
281
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                switch ((string)value)
                {
282
283
284
285
286
287
288
289
290
                    case "100": return SvgFontWeight.W100;
                    case "200": return SvgFontWeight.W200;
                    case "300": return SvgFontWeight.W300;
                    case "400": return SvgFontWeight.W400;
                    case "500": return SvgFontWeight.W500;
                    case "600": return SvgFontWeight.W600;
                    case "700": return SvgFontWeight.W700;
                    case "800": return SvgFontWeight.W800;
                    case "900": return SvgFontWeight.W900;
291
292
293
294
295
296
297
298
299
300
                }
            }
            return base.ConvertFrom(context, culture, value);
        }
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string) && value is SvgFontWeight)
            {
                switch ((SvgFontWeight)value)
                {
301
302
303
304
305
306
307
308
309
                    case SvgFontWeight.W100: return "100";
                    case SvgFontWeight.W200: return "200";
                    case SvgFontWeight.W300: return "300";
                    case SvgFontWeight.W400: return "400";
                    case SvgFontWeight.W500: return "500";
                    case SvgFontWeight.W600: return "600";
                    case SvgFontWeight.W700: return "700";
                    case SvgFontWeight.W800: return "800";
                    case SvgFontWeight.W900: return "900";
310
311
312
313
314
315
                }
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

316
317
318
319
320
    public sealed class SvgTextTransformationConverter : EnumBaseConverter<SvgTextTransformation>
    {
        public SvgTextTransformationConverter() : base(SvgTextTransformation.None) { }
    }

321
322
    public static class Enums 
    {
323
        [CLSCompliant(false)]
324
325
        public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct, IConvertible
        {
326
327
328
329
330
331
332
333
334
335
            try
            {
                result = (TEnum)Enum.Parse(typeof(TEnum), value, true);
                return true;
            }
            catch
            {
                result = default(TEnum);
                return false;
            }
336
337
        }
    }
338
}