// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) 2014 OxyPlot contributors // // -------------------------------------------------------------------------------------------------------------------- namespace ExampleLibrary { using System; using System.Collections.Generic; using System.Reflection; using ExampleLibrary.Utilities; using OxyPlot; /// /// Provides information about an example. /// public class ExampleInfo { /// /// The method to invoke. /// private readonly MethodInfo method; /// /// Indicates whether this instance was already initialized. /// private bool initialized; /// /// The un-modified example. /// private Example Example; /// /// The examples for this example info. /// private Dictionary examples; /// /// The options supported by this example. /// private ExampleFlags exampleSupport; /// /// Initializes a new instance of the class. /// /// The category. /// The title. /// The tags. /// The method. /// A value indiciating whether the example should be excluded from automated tests. public ExampleInfo(string category, string title, string[] tags, MethodInfo method, bool excludeFromAutomatedTests) { this.Category = category; this.Title = title; this.Tags = tags; this.method = method; this.ExcludeFromAutomatedTests = excludeFromAutomatedTests; } /// /// Gets the category. /// /// /// The category. /// public string Category { get; } /// /// Gets the code. /// /// /// The code. /// public string Code => this.PlotModel?.ToCode(); /// /// Gets a value indicating whether the plot model is reversible. /// public bool IsReversible { get { this.EnsureInitialized(); return exampleSupport.HasFlag(ExampleFlags.Reverse); } } /// /// Gets a value indicating whether the plot model is transposable. /// public bool IsTransposable { get { this.EnsureInitialized(); return exampleSupport.HasFlag(ExampleFlags.Transpose); } } /// /// Gets the code for the example with the given flags. /// /// The flags for the example. /// Code that produces the example. /// Ignores unsupported flags. public string GetCode(ExampleFlags flags) { return this.GetModel(flags)?.ToCode(); } /// /// Gets the for the example with the given flags. /// /// The flags for the example. /// The . /// Ignores unsupported flags. public PlotModel GetModel(ExampleFlags flags) { return this.GetExample(flags).Model; } /// /// Gets the for the example with the given flags. /// /// The flags for the example. /// The . /// Ignores unsupported flags. public IPlotController GetController(ExampleFlags flags) { return this.GetExample(flags).Controller; } /// /// Gets the with the given flags. /// /// The flags for the example. /// The . /// Ignores unsupported flags. private Example GetExample(ExampleFlags flags) { this.EnsureInitialized(); // ignore flags we don't support flags = FilterFlags(flags); if (!examples.TryGetValue(flags, out var example)) { example = GetDefaultExample(); if (flags.HasFlag(ExampleFlags.Transpose)) { example.Model.Transpose(); } if (flags.HasFlag(ExampleFlags.Reverse)) { example.Model.ReverseAllAxes(); } examples[flags] = example; } return example; } /// /// Gets the plot controller for the default example. /// /// /// The plot controller. /// public IPlotController PlotController { get { this.EnsureInitialized(); return this.Example.Controller; } } /// /// Gets the plot model for the default example. /// /// /// The plot model. /// public PlotModel PlotModel { get { this.EnsureInitialized(); return this.Example.Model; } } /// /// Gets the tags. /// /// /// The tags. /// public string[] Tags { get; } /// /// Gets a value indiciating whether this example should be excluded from automated tests. /// /// /// true if the example should be excluded from automated tests, otherwise false. /// public bool ExcludeFromAutomatedTests { get; } /// /// Gets the title. /// /// /// The title. /// public string Title { get; } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return this.Title; } /// /// Prepares from the given parameters. /// /// Whether to set the flag. /// Whether to set the flag. /// The . public static ExampleFlags PrepareFlags(bool transpose, bool reverse) { var flags = (ExampleFlags)0; if (transpose) { flags |= ExampleFlags.Transpose; } if (reverse) { flags |= ExampleFlags.Reverse; } return flags; } /// /// Initializes this instance if it is not already initialized. /// private void EnsureInitialized() { if (this.initialized) { return; } this.initialized = true; this.examples = new Dictionary(); this.Example = GetDefaultExample(); this.exampleSupport = PrepareFlags(this.Example.Model?.IsTransposable() == true, this.Example.Model?.IsReversible() == true); // remember the 'default' model: loads the transposed/reversed ones as we need them this.examples.Add(PrepareFlags(false, false), this.Example); } /// /// Gets a new instance of the default example. /// /// An . private Example GetDefaultExample() { var result = this.method.Invoke(null, null); if (result is null) { return new Example(null, null); } if (result is PlotModel plotModel) { return new Example(plotModel, null); } else if (result is Example example) { return example; } throw new Exception($"Unsupport type returned by example method for example {Category} > {Title}: {result.GetType().FullName}."); } /// /// Filters unsupported flags from the given flags. /// /// The original set of flags. /// The filtered flags. private ExampleFlags FilterFlags(ExampleFlags flags) { return flags & exampleSupport; } } }