diff --git a/src/Artemis.Core/Extensions/TypeExtensions.cs b/src/Artemis.Core/Extensions/TypeExtensions.cs index 223874f44..d6001d7ba 100644 --- a/src/Artemis.Core/Extensions/TypeExtensions.cs +++ b/src/Artemis.Core/Extensions/TypeExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Humanizer; namespace Artemis.Core { @@ -63,6 +64,25 @@ namespace Artemis.Core || value is decimal; } + private static readonly Dictionary TypeKeywords = new Dictionary() + { + {typeof(bool), "bool"}, + {typeof(byte), "byte"}, + {typeof(sbyte), "sbyte"}, + {typeof(char), "char"}, + {typeof(decimal), "decimal"}, + {typeof(double), "double"}, + {typeof(float), "float"}, + {typeof(int), "int"}, + {typeof(uint), "uint"}, + {typeof(long), "long"}, + {typeof(ulong), "ulong"}, + {typeof(short), "short"}, + {typeof(ushort), "ushort"}, + {typeof(object), "object"}, + {typeof(string), "string"}, + }; + // From https://stackoverflow.com/a/2224421/5015269 but inverted and renamed to match similar framework methods /// /// Determines whether an instance of a specified type can be casted to a variable of the current type @@ -127,5 +147,27 @@ namespace Artemis.Core return enumerableType?.GenericTypeArguments[0]; } + + /// + /// Determines a display name for the given type + /// + /// The type to determine the name for + /// Whether or not to humanize the result, defaults to false + /// + public static string GetDisplayName(this Type type, bool humanize = false) + { + if (!type.IsGenericType) + { + string displayValue = TypeKeywords.TryGetValue(type, out string? keyword) ? keyword! : type.Name; + return humanize ? displayValue.Humanize() : displayValue; + } + + Type genericTypeDefinition = type.GetGenericTypeDefinition(); + if (genericTypeDefinition == typeof(Nullable<>)) + return type.GenericTypeArguments[0].GetDisplayName(humanize) + "?"; + + string stripped = genericTypeDefinition.Name.Split('`')[0]; + return $"{stripped}<{string.Join(", ", type.GenericTypeArguments.Select(t => t.GetDisplayName(humanize)))}>"; + } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index 4b490c686..4fb72523f 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -260,7 +260,7 @@ namespace Artemis.UI.Shared if (typeViewModel != null) return new DataModelPropertyViewModel(DataModel, this, dataModelPath) {DisplayViewModel = typeViewModel, Depth = depth}; // For primitives, create a property view model, it may be null that is fine - if (propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(string)) + if (propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(string) || propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) return new DataModelPropertyViewModel(DataModel, this, dataModelPath) {Depth = depth}; if (propertyType.IsGenericEnumerable()) return new DataModelListViewModel(DataModel, this, dataModelPath) {Depth = depth}; diff --git a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs index abe0bf469..28709b186 100644 --- a/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs +++ b/src/Plugins/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs @@ -12,12 +12,17 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels ListItems = new List(); for (int i = 0; i < 20; i++) ListItems.Add(new SomeListItem {ItemName = $"Item {i + 1}", Number = i}); + + GenericTest = new Test {Value = "Generic string value"}; } // Your datamodel can have regular properties and you can annotate them if you'd like [DataModelProperty(Name = "A test string", Description = "It doesn't do much, but it's there.")] public string TemplateDataModelString { get; set; } + public int? NullableInt { get; set; } + public Test GenericTest { get; set; } + public SKColor TestColorA { get; set; } public SKColor TestColorB { get; set; } @@ -31,6 +36,11 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels public List ListItems { get; set; } } + public class Test + { + public T Value { get; set; } + } + public class SomeListItem { public string ItemName { get; set; }