Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: SkylineCommunications/Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9.0.6
Choose a base ref
...
head repository: SkylineCommunications/Skyline.DataMiner.Utils.InteractiveAutomationScriptToolkit
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9.0.X
Choose a head ref
  • 17 commits
  • 10 files changed
  • 3 contributors

Commits on Jan 21, 2025

  1. Add content file to automatically add it to every project referencing…

    … the IAS toolkit.
    ThomasRemmery committed Jan 21, 2025
    Copy the full SHA
    78542c5 View commit details

Commits on Jan 22, 2025

  1. Do not update the previous and Selected fields of a dropdown if nothi…

    …ng changed.
    ThomasRemmery committed Jan 22, 2025
    Copy the full SHA
    32ab3c5 View commit details
  2. Copy the full SHA
    79cbf7f View commit details
  3. Merge pull request #23 from VictorScherpereell/9.0.X

    Added try-catch around Engine.ShowUI to throw a new exception with more details.
    ThomasRemmery authored Jan 22, 2025
    Copy the full SHA
    5878a9c View commit details
  4. Revert "Do not update the previous and Selected fields of a dropdown …

    …if nothing changed."
    
    This reverts commit 32ab3c5.
    ThomasRemmery committed Jan 22, 2025
    Copy the full SHA
    d55841c View commit details
  5. Revert "Add content file to automatically add it to every project ref…

    …erencing the IAS toolkit."
    
    This reverts commit 78542c5.
    ThomasRemmery committed Jan 22, 2025
    Copy the full SHA
    142f312 View commit details

Commits on Jan 23, 2025

  1. Copy the full SHA
    07f62aa View commit details
  2. Merge pull request #24 from VictorScherpereell/9.0.X

    Handling InteractiveUserDetachedException separately
    ThomasRemmery authored Jan 23, 2025
    Copy the full SHA
    6d63ed0 View commit details

Commits on Feb 5, 2025

  1. Update README.md

    Replace Run with ShowDialog
    ThomasRemmery authored Feb 5, 2025
    Copy the full SHA
    86447f7 View commit details
  2. Update README.md

    ThomasRemmery authored Feb 5, 2025
    Copy the full SHA
    b68e76c View commit details
  3. Update README.md

    ThomasRemmery authored Feb 5, 2025
    Copy the full SHA
    1c11a25 View commit details
  4. Update README.md

    ThomasRemmery authored Feb 5, 2025
    Copy the full SHA
    a9bac32 View commit details

Commits on Feb 7, 2025

  1. Copy the full SHA
    e1d0e4d View commit details
  2. Copy the full SHA
    f8f54fb View commit details
  3. Copy the full SHA
    47f6f00 View commit details
  4. Added unittests for conversion constructors of enum widgets

    ThomasRemmery committed Feb 7, 2025
    Copy the full SHA
    ebdc5a5 View commit details

Commits on Feb 21, 2025

  1. Fix bug that provided conversion function would be bypassed when usin…

    …g the SetOptions and Values.Set on an EnumDropDown and EnumRadioButtonList.
    ThomasRemmery committed Feb 21, 2025
    Copy the full SHA
    af1ce97 View commit details
96 changes: 96 additions & 0 deletions InteractiveAutomationToolkit/Components/Generics/EnumDropDown.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
namespace Skyline.DataMiner.Utils.InteractiveAutomationScript
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

/// <summary>
/// A dropdown that allows users to select a value defined by an enum.
/// </summary>
/// <typeparam name="T">Enum type to represent with the dropdown.</typeparam>
/// <example>
/// <code>
/// public enum Capitol
/// {
/// Brussels,
/// [Description("Washington DC")]
/// WashingtonDc,
/// [Description("Buenos Aires")]
/// BuenosAires,
/// Lisbon,
/// Cairo,
/// Paris
/// }
///
/// var capitolDropDown = new EnumDropDown&lt;Capitol&gt;();
/// var selectedCapitol = capitolDropDown.Selected;
/// capitolDropDown.Changed += (s, e) =>
/// {
/// engine.Log($"Capitol changed from {e.Previous} to {e.Selected}");
/// selectedCapitol = e.Selected;
/// };
/// </code>
/// </example>
public class EnumDropDown<T> : DropDown<T> where T : struct, Enum
{
private readonly Func<T, string> convertValueToString;

/// <summary>
/// Initializes a new instance of the <see cref="EnumDropDown{T}"/>
/// </summary>
/// <param name="exclude">Values of the enum to exclude as options from the dropdown.</param>
/// <remarks>
/// The display value of the enum is determined by the presence of the <see cref="DescriptionAttribute"/>.
/// If this attribute isn't defined, the .ToString() representation is used.
/// </remarks>
public EnumDropDown(ICollection<T> exclude = null) : this(DefaultConversion, exclude) { }

/// <summary>
/// Initializes a new instance of the <see cref="EnumDropDown{T}"/>
/// </summary>
/// <param name="convertValueToString">Function to map the enum value to its string representation.</param>
/// <param name="exclude">Values of the enum to exclude as options from the dropdown.</param>
public EnumDropDown(Func<T, string> convertValueToString, ICollection<T> exclude = null)
{
this.convertValueToString = convertValueToString ?? throw new ArgumentNullException(nameof(convertValueToString));

var options = new List<Option<T>>();

var type = typeof(T);
var values = Enum.GetValues(type).Cast<T>();

foreach (var value in values)
{
if (exclude != null && exclude.Contains(value))
{
continue;
}

options.Add(new Option<T>(convertValueToString(value), value));
}

Options = options;
}

public override void SetOptions(IEnumerable<T> options)
{
base.SetOptions(options.Select(x => new Option<T>(convertValueToString(x), x)));
}

public override IEnumerable<T> Values
{
get => base.Values;
set
{
if (value == null) throw new ArgumentNullException(nameof(value));
SetOptions(value.Select(x => new Option<T>(convertValueToString(x), x)));
}
}

private static string DefaultConversion(T value)
{
return value.GetDescription();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
namespace Skyline.DataMiner.Utils.InteractiveAutomationScript
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

/// <summary>
/// A radio button list that allows users to select a value defined by an enum.
/// </summary>
/// <typeparam name="T">Enum type to represent with the radio button list.</typeparam>
/// /// <example>
/// <code>
/// public enum Capitol
/// {
/// None,
/// Brussels,
/// [Description("Washington DC")]
/// WashingtonDc,
/// [Description("Buenos Aires")]
/// BuenosAires,
/// Lisbon,
/// Cairo,
/// Paris
/// }
///
/// var capitolRadioButtonList = new EnumRadioButtonList&lt;Capitol&gt;(new [] { Capitol.None });
/// Capitol selectedCapitol = capitolRadioButtonList.Selected;
/// capitolRadioButtonList.Changed += (s, e) =>
/// {
/// engine.Log($"Capitol changed from {e.Previous} to {e.Selected}");
/// selectedCapitol = e.Selected;
/// };
/// </code>
/// </example>
public class EnumRadioButtonList<T> : RadioButtonList<T> where T : struct, Enum
{
private readonly Func<T, string> convertValueToString;

/// <summary>
/// Initializes a new instance of the <see cref="EnumRadioButtonList{T}"/>
/// </summary>
/// <param name="exclude">Values of the enum to exclude as options from the radio button list.</param>
/// <remarks>
/// The display value of the enum is determined by the presence of the <see cref="DescriptionAttribute"/>.
/// If this attribute isn't defined, the .ToString() representation is used.
/// </remarks>
public EnumRadioButtonList(ICollection<T> exclude = null) : this(DefaultConversion, exclude) { }

/// <summary>
/// Initializes a new instance of the <see cref="EnumRadioButtonList{T}"/>
/// </summary>
/// <param name="convertValueToString">Function to map the enum value to its string representation.</param>
/// <param name="exclude">Values of the enum to exclude as options from the radio button list.</param>
public EnumRadioButtonList(Func<T, string> convertValueToString, ICollection<T> exclude = null)
{
this.convertValueToString = convertValueToString ?? throw new ArgumentNullException(nameof(convertValueToString));

var options = new List<Option<T>>();

var type = typeof(T);
var values = Enum.GetValues(type).Cast<T>();

foreach (var value in values)
{
if (exclude != null && exclude.Contains(value))
{
continue;
}

options.Add(new Option<T>(convertValueToString(value), value));
}

Options = options;
}

public override void SetOptions(IEnumerable<T> options)
{
base.SetOptions(options.Select(x => new Option<T>(convertValueToString(x), x)));
}

public override IEnumerable<T> Values
{
get => base.Values;
set
{
if (value == null) throw new ArgumentNullException(nameof(value));
SetOptions(value.Select(x => new Option<T>(convertValueToString(x), x)));
}
}

private static string DefaultConversion(T value)
{
return value.GetDescription();
}
}
}
Original file line number Diff line number Diff line change
@@ -118,7 +118,6 @@ public virtual IEnumerable<T> Values
}

/// <inheritdoc/>
/// <param name="option">Option to add.</param>
/// <exception cref="ArgumentNullException">When options is null.</exception>
public void AddOption(Option<T> option)
{
Original file line number Diff line number Diff line change
@@ -188,7 +188,7 @@ public void SetOptions(IEnumerable<Option<T>> options)

/// <inheritdoc/>
/// <exception cref="ArgumentNullException">When options is null.</exception>
public void SetOptions(IEnumerable<T> options)
public virtual void SetOptions(IEnumerable<T> options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
SetOptions(options.Select(x => new Option<T>(x)));
Original file line number Diff line number Diff line change
@@ -231,7 +231,7 @@ public void SetOptions(IEnumerable<Option<T>> options)

/// <inheritdoc/>
/// <exception cref="ArgumentNullException">When options is null.</exception>
public void SetOptions(IEnumerable<T> options)
public virtual void SetOptions(IEnumerable<T> options)
{
if (options == null) throw new ArgumentNullException(nameof(options));
SetOptions(options.Select(x => new Option<T>(x)));
28 changes: 21 additions & 7 deletions InteractiveAutomationToolkit/Dialogs/Dialog.cs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
using System.Linq;

using Skyline.DataMiner.Automation;
using Skyline.DataMiner.Net.Exceptions;

/// <summary>
/// A dialog represents a single window that can be shown.
@@ -594,17 +595,30 @@ public void SetWidgetLayout(Widget widget, IWidgetLayout widgetLayout)
/// <param name="requireResponse">If the dialog expects user interaction.</param>
/// <remarks>Should only be used when you create your own event loop.</remarks>
public void Show(bool requireResponse = true)
{
UIBuilder uib = Build();
uib.RequireResponse = requireResponse;
{
UIBuilder uiBuilder = Build();
uiBuilder.RequireResponse = requireResponse;

IUIResults uir = new WrappedUIResults(Engine.ShowUI(uib));
IUIResults uiResults;

if (requireResponse)
try
{
LoadChanges(uir);
RaiseResultEvents(uir);
uiResults = new WrappedUIResults(Engine.ShowUI(uiBuilder));
}
catch(InteractiveUserDetachedException)
{
throw;
}
catch (DataMinerException e)
{
throw new InvalidOperationException($"{nameof(IEngine)}.{nameof(Engine.ShowUI)} failed with {nameof(UIBuilder)} argument {uiBuilder}", e);
}

if (requireResponse)
{
LoadChanges(uiResults);
RaiseResultEvents(uiResults);
}
}

/// <summary>
18 changes: 18 additions & 0 deletions InteractiveAutomationToolkit/Extensions/EnumExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Skyline.DataMiner.Utils.InteractiveAutomationScript
{
using System;
using System.ComponentModel;
using System.Linq;

internal static class EnumExtensions
{
public static string GetDescription(this Enum value)
{
var enumField = value.GetType().GetField(value.ToString()) ?? throw new InvalidOperationException($"Value '{value}' is not a valid enum value");

var attribute = enumField.GetCustomAttributes(typeof(DescriptionAttribute), false).SingleOrDefault() as DescriptionAttribute;

return attribute == null ? value.ToString() : attribute.Description;
}
}
}
Loading