Table of Contents

Settings

The settings window of an extension is generated from its public properties: this is how a chart indicator, a heatmap indicator, a column or a module gets its settings, and the attributes below work the same for all of them. The examples use a chart indicator.

A property as a setting

A public property with a getter and a setter is shown in the settings window and saved with the chart. A chart indicator that depends on the value must recalculate when it changes: call RecalculateValues from the setter. It clears all the data series of the indicator and calculates every bar again, so do not call it when the value has not changed.

[OFT.Attributes.Parameter]
public int Size
{
    get => _size;
    set
    {
        if (_size == value)
            return;

        _size = value;
        RecalculateValues();
    }
}

The values of the properties marked with [Parameter] are added to the description of the indicator (the text in brackets after its name, for example in the list of selected indicators); the built-in indicators mark their main parameters this way. The platform assemblies also contain the obsolete ATAS.Indicators.ParameterAttribute, which [Parameter] binds to in a namespace under ATAS.Indicators; write the attribute with its namespace there, as above.

[Display] (System.ComponentModel.DataAnnotations) gives the setting its name, its group and its position in the group:

[Display(GroupName = "Settings", Name = "Type", Order = 10)]
public int Type { get; set; }

Types of settings

The built-in SampleProperties indicator shows every kind of setting at once.

Values

int, decimal, bool, string, DateTime, TimeSpan, enums and colors are edited with the matching editor:

[Display(Name = "Integer", GroupName = "Examples")]
public int Integer { get; set; }

[Display(Name = "Decimal", GroupName = "Examples")]
public decimal Decimal { get; set; }

[Display(Name = "Boolean", GroupName = "Examples")]
public bool Boolean { get; set; }

[Display(Name = "Heatmap", GroupName = "Examples")]
public HeatmapTypes HeatmapType { get; set; }

[Display(Name = "Date", GroupName = "Examples")]
public DateTime DateTime { get; set; } = new(2020, 01, 01);

[Display(Name = "Label", GroupName = "Examples")]
public string Label { get; set; } = "Some Label";

Settings of the value types

The color of a setting is System.Windows.Media.Color (the drawing API takes System.Drawing.Color; the Convert() extension method of ATAS.Indicators converts one to the other).

Filters

A Filter is a value with an Enabled check box: one setting both stores the value and switches it on and off. Besides Filter (a decimal), there are FilterInt, FilterString, FilterBool, FilterColor, FilterTimeSpan, FilterKey, FilterRangeInt, FilterRenderPen and FilterEnum<TEnum>. Initialize the property at once. The filter raises PropertyChanged when its value or its check box changes; instead of subscribing, a handler of the new value can be passed to ValueOnChanged. SetValueSilently changes the value without raising the event and without calling that handler. Passing false to the constructor (new FilterInt(false)) hides the check box.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

using ATAS.Indicators;

namespace ATAS.Docs.Samples.CommonApi;

public class FilterSettingsIndicator : Indicator
{
    [Display(Name = "Filter Decimal", GroupName = "Examples")]
    public Filter FilterDecimal { get; set; } = new();

    [Display(Name = "Filter Integer", GroupName = "Examples")]
    public FilterInt FilterInt { get; set; } = new();

    [Display(Name = "Filter Text", GroupName = "Examples")]
    public FilterString FilterText { get; set; } = new() { Enabled = true, Value = "Value" };

    public FilterSettingsIndicator() : base(true)
    {
        DenyToChangePanel = true;
        DataSeries[0].IsHidden = true;

        FilterDecimal.PropertyChanged += OnFilterPropertyChanged;
        FilterInt.PropertyChanged += OnFilterPropertyChanged;
        FilterText.PropertyChanged += OnFilterPropertyChanged;
    }

    protected override void OnCalculate(int bar, decimal value)
    {
    }

    private void OnFilterPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        RecalculateValues();
    }
}

Filter settings

Collections

A collection setting is an ObservableCollection<T>; the user adds and removes elements in the settings window. For the collection to be saved and restored correctly, mark it with [JsonProperty(ObjectCreationHandling = Replace)] of Newtonsoft.Json (the platform ships the library; reference the Newtonsoft.Json package with ExcludeAssets="runtime", so that your build does not carry its own copy).

using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;

using ATAS.Indicators;
using Newtonsoft.Json;

namespace ATAS.Docs.Samples.CommonApi;

public class CollectionSettingsIndicator : Indicator
{
    [Display(Name = "Numbers", GroupName = "Examples")]
    [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
    public ObservableCollection<decimal> Numbers { get; set; } = new() { 1.0m, 2.0m, 3.0m };

    [Display(Name = "Filters", GroupName = "Examples")]
    [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
    public ObservableCollection<Filter> Filters { get; set; } = new();

    [Display(Name = "Colors", GroupName = "Examples")]
    [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
    public ObservableCollection<Color> ColorsSource { get; set; } = new() { Colors.Red, Colors.Green, Colors.Blue };

    public CollectionSettingsIndicator() : base(true)
    {
        DenyToChangePanel = true;
        DataSeries[0].IsHidden = true;
    }

    protected override void OnCalculate(int bar, decimal value)
    {
    }
}

Collection settings

Editors and validation

Attributes refine how a setting is edited; the Attribute suffix of their names can be dropped.

  • NumericEditor: the minimum, the maximum, the step and the display format of a number.
  • ComboBoxEditor: a drop-down list; the items come from a collection type, with the members to display and to store.
[Display(Name = "Selector", GroupName = "Examples")]
[ComboBoxEditor(typeof(EntitiesSource), DisplayMember = nameof(Entity.Name), ValueMember = nameof(Entity.Value))]
public int? Selector { get; set; }

[Display(Name = "Decimal", GroupName = "Examples")]
[NumericEditor(0.0, 100.0, Step = 0.5, DisplayFormat = "F2")]
public decimal Decimal { get; set; }
  • [Range] and [DisplayFormat] (System.ComponentModel.DataAnnotations): the allowed range and the format of a number.
[Display(Name = "Range", GroupName = "Examples")]
[Range(-100, 100)]
[DisplayFormat(DataFormatString = "##0.0##")]
public decimal RangeValue { get; set; }
  • [RegularExpression]: the value must match the expression. Mask: the editor accepts only input that matches the mask.
[Display(Name = "E-mail", GroupName = "Examples")]
[RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$")]
public string Email { get; set; } = "";

[Display(Name = "Time Span", GroupName = "Examples")]
[Mask(MaskTypes.DateTimeAdvancingCaret, "HH:mm:ss")]
public TimeSpan TimeSpan { get; set; } = new(1, 0, 0);
  • [Browsable(false)] (System.ComponentModel) hides a public property from the settings window.
[Browsable(false)]
public int NoBrowsable { get; set; }

More attributes: VisibleWhen, EnabledWhen and Tab in OFT.Attributes; IsExpanded, TextEditor, SelectFileEditor and SoundComboBoxEditor in OFT.Attributes.Editors. The SampleProperties indicator shows several of them. A chart indicator can also expand and collapse its groups from code: Collapsing settings categories.