313
Source/Examples/ExampleLibrary/ExampleInfo.cs
Normal file
313
Source/Examples/ExampleLibrary/ExampleInfo.cs
Normal file
@@ -0,0 +1,313 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ExampleInfo.cs" company="OxyPlot">
|
||||
// Copyright (c) 2014 OxyPlot contributors
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace ExampleLibrary
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using ExampleLibrary.Utilities;
|
||||
|
||||
using OxyPlot;
|
||||
|
||||
/// <summary>
|
||||
/// Provides information about an example.
|
||||
/// </summary>
|
||||
public class ExampleInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The method to invoke.
|
||||
/// </summary>
|
||||
private readonly MethodInfo method;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this instance was already initialized.
|
||||
/// </summary>
|
||||
private bool initialized;
|
||||
|
||||
/// <summary>
|
||||
/// The un-modified example.
|
||||
/// </summary>
|
||||
private Example Example;
|
||||
|
||||
/// <summary>
|
||||
/// The examples for this example info.
|
||||
/// </summary>
|
||||
private Dictionary<ExampleFlags, Example> examples;
|
||||
|
||||
/// <summary>
|
||||
/// The options supported by this example.
|
||||
/// </summary>
|
||||
private ExampleFlags exampleSupport;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExampleInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="category">The category.</param>
|
||||
/// <param name="title">The title.</param>
|
||||
/// <param name="tags">The tags.</param>
|
||||
/// <param name="method">The method.</param>
|
||||
/// <param name="excludeFromAutomatedTests">A value indiciating whether the example should be excluded from automated tests.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the category.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The category.
|
||||
/// </value>
|
||||
public string Category { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the code.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The code.
|
||||
/// </value>
|
||||
public string Code => this.PlotModel?.ToCode();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the plot model is reversible.
|
||||
/// </summary>
|
||||
public bool IsReversible
|
||||
{
|
||||
get
|
||||
{
|
||||
this.EnsureInitialized();
|
||||
return exampleSupport.HasFlag(ExampleFlags.Reverse);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the plot model is transposable.
|
||||
/// </summary>
|
||||
public bool IsTransposable
|
||||
{
|
||||
get
|
||||
{
|
||||
this.EnsureInitialized();
|
||||
return exampleSupport.HasFlag(ExampleFlags.Transpose);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the code for the example with the given flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags for the example.</param>
|
||||
/// <returns>Code that produces the example.</returns>
|
||||
/// <remarks>Ignores unsupported flags.</remarks>
|
||||
public string GetCode(ExampleFlags flags)
|
||||
{
|
||||
return this.GetModel(flags)?.ToCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="PlotModel"/> for the example with the given flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags for the example.</param>
|
||||
/// <returns>The <see cref="PlotModel"/>.</returns>
|
||||
/// <remarks>Ignores unsupported flags.</remarks>
|
||||
public PlotModel GetModel(ExampleFlags flags)
|
||||
{
|
||||
return this.GetExample(flags).Model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IPlotController"/> for the example with the given flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags for the example.</param>
|
||||
/// <returns>The <see cref="IPlotController"/>.</returns>
|
||||
/// <remarks>Ignores unsupported flags.</remarks>
|
||||
public IPlotController GetController(ExampleFlags flags)
|
||||
{
|
||||
return this.GetExample(flags).Controller;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Example"/> with the given flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags for the example.</param>
|
||||
/// <returns>The <see cref="Example"/>.</returns>
|
||||
/// <remarks>Ignores unsupported flags.</remarks>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot controller for the default example.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The plot controller.
|
||||
/// </value>
|
||||
public IPlotController PlotController
|
||||
{
|
||||
get
|
||||
{
|
||||
this.EnsureInitialized();
|
||||
return this.Example.Controller;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plot model for the default example.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The plot model.
|
||||
/// </value>
|
||||
public PlotModel PlotModel
|
||||
{
|
||||
get
|
||||
{
|
||||
this.EnsureInitialized();
|
||||
return this.Example.Model;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tags.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The tags.
|
||||
/// </value>
|
||||
public string[] Tags { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indiciating whether this example should be excluded from automated tests.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the example should be excluded from automated tests, otherwise <c>false</c>.
|
||||
/// </value>
|
||||
public bool ExcludeFromAutomatedTests { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The title.
|
||||
/// </value>
|
||||
public string Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares <see cref="ExampleFlags"/> from the given parameters.
|
||||
/// </summary>
|
||||
/// <param name="transpose">Whether to set the <see cref="ExampleFlags.Transpose"/> flag.</param>
|
||||
/// <param name="reverse">Whether to set the <see cref="ExampleFlags.Reverse"/> flag.</param>
|
||||
/// <returns>The <see cref="ExampleFlags"/>.</returns>
|
||||
public static ExampleFlags PrepareFlags(bool transpose, bool reverse)
|
||||
{
|
||||
var flags = (ExampleFlags)0;
|
||||
|
||||
if (transpose)
|
||||
{
|
||||
flags |= ExampleFlags.Transpose;
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
flags |= ExampleFlags.Reverse;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance if it is not already initialized.
|
||||
/// </summary>
|
||||
private void EnsureInitialized()
|
||||
{
|
||||
if (this.initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
this.examples = new Dictionary<ExampleFlags, Example>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new instance of the default example.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="Example"/>.</returns>
|
||||
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}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters unsupported flags from the given flags.
|
||||
/// </summary>
|
||||
/// <param name="flags">The original set of flags.</param>
|
||||
/// <returns>The filtered flags.</returns>
|
||||
private ExampleFlags FilterFlags(ExampleFlags flags)
|
||||
{
|
||||
return flags & exampleSupport;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user