// Copyright Keysight Technologies 2012-2019 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.Globalization; using System.Linq; using OpenTap.Translation; namespace OpenTap { /// /// Defines how a property, class, enum, or other item is presented to the user. /// Also configures the description and allows items to be grouped and ordered. /// public class DisplayAttribute : Attribute, IDisplayAnnotation { internal const string GroupSeparator = " \\ "; /// Optional text that provides a description of the item. /// Consider using HelpLinkAttribute if a link to documentation is needed. /// public string Description { get; } /// Optional text used to group displayed items. /// Use 'Groups' if more than one level of grouping is needed. /// public string[] Group { get; } /// Name displayed by the UI. public string Name { get; } /// The language of this attribute.. public CultureInfo Language { get; } /// Optional double that ranks items and groups in ascending order relative to other items/groups. /// Default is -10000. For a group, the order is the average order of the elements inside the group. /// Any double value is allowed. Items with same order are ranked alphabetically. /// /// /// This applies only to properties. Classes will ignore this setting and be ordered alphabetically. /// public double Order { get; } /// Boolean setting that indicates whether a group's default appearance is collapsed. /// Default is 'false' (group is expanded). /// public bool Collapsed { get; } /// If the owning DisplayAttribute is a translated display attribute, this property will be set to the neutral (non-translated) variant. /// If the owning DisplayAttribute is not translated, this will be null. /// public DisplayAttribute NeutralDisplayAttribute { get; internal set; } string fullName = null; /// Gets the Group (or Groups) and Name concatenated with a backslash (\). public string GetFullName() { if(fullName == null) { if (Group.Length == 0) fullName = Name; else fullName = string.Join(GroupSeparator, Group.Append(Name)); } return fullName; } /// /// The default order for display attribute. This is set in this way to highlight the fact that /// an order is not set and out of the range of normally selected order values. '0' for example /// is a commonly selected value for order, so it could not be that. /// public const double DefaultOrder = -10000.0; /// /// Creates a new instance of . Ensures that Name is never null. /// /// Name displayed by the UI. /// Optional text that provides a description of the item. Consider using HelpLinkAttribute if a link to documentation is needed. /// Optional text used to group displayed items. Use 'Groups' if more than one level of grouping is needed. /// Optional double that ranks items and groups in ascending order relative to other items/groups. Default is defined by DisplayAttribute.DefaultOrder. /// For a group, the order is the average order of the elements inside the group. Any double value is allowed. Items with same order are ranked alphabetically. /// Boolean setting that indicates whether a group's default appearance is collapsed. Default is 'false' (group is expanded). /// Optional array of text strings to specify multiple levels of grouping. Use 'Group' if only one level of grouping is needed. public DisplayAttribute(string Name, string Description = null, string Group = null, double Order = DefaultOrder, bool Collapsed = false, string[] Groups = null) { this.Name = Name ?? throw new ArgumentNullException(nameof(Name)); this.Description = Description; if (Groups != null) this.Group = Groups; else if (Group != null) this.Group = new[] { Group }; else this.Group = Array.Empty(); this.Order = Order; this.Collapsed = Collapsed; this.Language = TranslationManager.NeutralLanguage; } /// /// Creates a new instance of . Ensures that Name is never null. /// /// Name displayed by the UI. /// Optional text that provides a description of the item. Consider using HelpLinkAttribute if a link to documentation is needed. /// Optional text used to group displayed items. Use 'Groups' if more than one level of grouping is needed. /// Optional double that ranks items and groups in ascending order relative to other items/groups. Default is defined by DisplayAttribute.DefaultOrder. /// For a group, the order is the average order of the elements inside the group. Any double value is allowed. Items with same order are ranked alphabetically. /// Boolean setting that indicates whether a group's default appearance is collapsed. Default is 'false' (group is expanded). /// Optional array of text strings to specify multiple levels of grouping. Use 'Group' if only one level of grouping is needed. /// The language of this attribute. public DisplayAttribute(CultureInfo Language, string Name, string Description = null, string Group = null, double Order = DefaultOrder, bool Collapsed = false, string[] Groups = null) : this(Name, Description, Group, Order, Collapsed, Groups) { this.Language = Language; } /// Overriding Equals to fix strange equality issues between instances of DisplayAttribute. public override bool Equals(object obj) { if(object.ReferenceEquals(this, obj)) return true; if (obj is DisplayAttribute other) return other.Name == Name && Group.SequenceEqual(other.Group) && other.Description == Description && other.Order == Order; return false; } /// Generates a hash code based on the display attribute values. public override int GetHashCode() { int h = Name.GetHashCode(); foreach (var elem in Group) h = h * 31241231 + elem.GetHashCode(); return h; } } }