Skip to content

Commit

Permalink
add Plot API to Cookbook
Browse files Browse the repository at this point in the history
  • Loading branch information
swharden committed Feb 1, 2021
1 parent 31ab5f9 commit b778947
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 4 deletions.
93 changes: 91 additions & 2 deletions src/cookbook/ScottPlot.Cookbook/Site/IndexPage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace ScottPlot.Cookbook.Site
Expand All @@ -22,6 +24,93 @@ public void AddLinksToRecipes()
DivEnd();
}

private void AddTableRow(string[] columnNames, bool header = false)
{
string trStyle = header ? "style='font-weight: 600; background-color: #f6f8fa;'" : "";
AddHTML($"<tr {trStyle}>");
foreach (var name in columnNames)
AddHTML($"<td>{name}</td>");
AddHTML("</tr>");
}

public void AddPlotApiTableWithoutPlottables(XmlDoc xd, MethodInfo[] plotMethods, string linkPrefix = "")
{
AddGroupHeader("Methods to Manipulate Plots");
AddHTML("These methods act on the Plot to configure styling or behavior.");

AddHTML("<table>");
AddTableRow(new string[] { "Method", "Summary" }, true);

foreach (MethodInfo mi in plotMethods)
{
bool isAddPlottableMethod = mi.Name.StartsWith("Add") && mi.Name.Length > 3 && !mi.Name.Contains("Axis");
if (isAddPlottableMethod)
continue;
string summary = xd.GetSummary(mi);

string url = Sanitize(mi.Name);
string name = $"<a href='{linkPrefix}#{url}'><strong>{mi.Name}</strong></a>";
AddTableRow(new string[] { name, summary });
}

AddHTML("</table>");
}

public void AddPlotApiTablePlottables(XmlDoc xd, MethodInfo[] plotMethods, string linkPrefix = "")
{
AddGroupHeader("Helper Methods for Adding Plottables");
AddHTML("These methods make it easy to add specific plottable to the plot. ");
AddHTML("Common styling configuration is available as optional arguments, and these methods return " +
"the plottable they create so you can interact with it directly to further customize styling " +
"or udpate data after adding it to the plot.");

AddHTML("<table>");
AddTableRow(new string[] { "Method", "Summary" }, true);

foreach (MethodInfo mi in plotMethods)
{
bool isAddPlottableMethod = mi.Name.StartsWith("Add") && mi.Name.Length > 3 && !mi.Name.Contains("Axis");
if (!isAddPlottableMethod)
continue;
string summary = xd.GetSummary(mi);

string url = Sanitize(mi.Name);
string name = $"<a href='{linkPrefix}#{url}'><strong>{mi.Name}</strong></a>";
AddTableRow(new string[] { name, summary });
}

AddHTML("</table>");
}

public void AddPlotApiDetails(XmlDoc xd, MethodInfo[] plotMethods)
{
foreach (MethodInfo mi in plotMethods)
{
string name = mi.Name;
string url = Sanitize(name);
string summary = xd.GetSummary(mi);
string returnType = XmlDoc.PrettyType(mi.ReturnType);
string signature = XmlDoc.PrettySignature(mi);

AddGroupHeader(name, marginTop: "4em");

AddHTML($"<div><strong>Summary:</strong></div>");
AddHTML($"<ul><li>{summary}</li></ul>");

AddHTML($"<div><strong>Parameters:</strong></div>");
AddHTML("<ul>");
foreach (var p in mi.GetParameters())
AddHTML($"<li><code>{XmlDoc.PrettyType(p.ParameterType)}</code> {p.Name}</li>");
AddHTML("</ul>");

AddHTML($"<div><strong>Returns:</strong></div>");
AddHTML($"<ul><li><code>{returnType}</code></li></ul>");

AddHTML($"<div><strong>Signature:</strong></div>");
AddHTML($"<ul><li><code>{signature}</code></li></ul>");
}
}

private void AddRecipeGroup(string groupName, IRecipe[] recipes)
{
DivStart("categorySection");
Expand All @@ -31,10 +120,10 @@ private void AddRecipeGroup(string groupName, IRecipe[] recipes)
DivEnd();
}

private void AddGroupHeader(string title)
private void AddGroupHeader(string title, string marginTop = "1em")
{
string anchor = Sanitize(title);
SB.AppendLine($"<h2 style='margin-top: 1em;'>");
SB.AppendLine($"<h2 style='margin-top: {marginTop};'>");
SB.AppendLine($"<a href='#{anchor}' name='{anchor}' style='color: black; text-decoration: none; font-weight: 600;'>{title}</a>");
SB.AppendLine($"</h2>");
}
Expand Down
14 changes: 14 additions & 0 deletions src/cookbook/ScottPlot.Cookbook/XmlDoc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,19 @@ public static string PrettyType(Type type)

return pretty;
}

/// <summary>
/// Return a pretty formatted function signature
/// </summary>
public static string PrettySignature(MethodInfo mi, bool returnType = false)
{
string funcName = returnType ? PrettyType(mi.ReturnType) + " " : "";
funcName = funcName + mi.DeclaringType.Name + "." + mi.Name;
if (mi.IsGenericMethod)
funcName += "<T>";
string ps = string.Join(", ", mi.GetParameters().Select(p => $"{PrettyType(p.ParameterType)} {p.Name}"));
funcName += $"({ps})";
return funcName;
}
}
}
32 changes: 32 additions & 0 deletions src/tests/Cookbook/Generate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

Expand All @@ -13,6 +14,20 @@ class Generate
const string SourceFolder = "../../../../cookbook/ScottPlot.Cookbook";
const string CookbookFolder = "./cookbook";
const string RecipeFolder = "./cookbook/source";
const string XmlDocPath = "../../../../../src/ScottPlot/ScottPlot.xml";
XmlDoc XD;
MethodInfo[] PlotMethods;

[OneTimeSetUp]
public void Setup()
{
XD = new XmlDoc(XmlDocPath);
PlotMethods = typeof(ScottPlot.Plot).GetMethods()
.Where(x => x.IsPublic)
.Where(x => !x.GetCustomAttributes<ObsoleteAttribute>().Any())
.OrderBy(x => x.Name)
.ToArray();
}

[Test]
public void Test_Cookbook_Generate()
Expand All @@ -22,6 +37,7 @@ public void Test_Cookbook_Generate()
BuildRecipeImagesAndCode();
CopyResourceFiles();
BuildRecipePages();
BuildApiPage();
BuildIndexPage();
}

Expand Down Expand Up @@ -79,10 +95,26 @@ private void BuildRecipePages()
allPage.SaveAs("all_recipes.html", "All Recipes");
}

private void BuildApiPage()
{
var index = new ScottPlot.Cookbook.Site.IndexPage(CookbookFolder, SourceFolder);
index.AddPlotApiTableWithoutPlottables(XD, PlotMethods);
index.AddPlotApiTablePlottables(XD, PlotMethods);
index.AddPlotApiDetails(XD, PlotMethods);
index.SaveAs("api.html", "Plot API");
}

private void BuildIndexPage()
{
var index = new ScottPlot.Cookbook.Site.IndexPage(CookbookFolder, SourceFolder);

// add recipes
index.AddLinksToRecipes();

// add API table
index.AddPlotApiTableWithoutPlottables(XD, PlotMethods, "api.html");
index.AddPlotApiTablePlottables(XD, PlotMethods, "api.html");

index.SaveAs("index.html", null);
Console.WriteLine($"View Cookbook: {System.IO.Path.GetFullPath(CookbookFolder)}/index.html");
}
Expand Down
4 changes: 2 additions & 2 deletions src/tests/Documentation/ApiMarkdown.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void Test_API_Plot()
sb.AppendLine();
sb.AppendLine($"This document was generated for `ScottPlot {ScottPlot.Plot.Version}`");

// add a table at the top
// table without AddPlottable() methods
sb.AppendLine("### Methods to Manipulate the Plot");
sb.AppendLine("Method | Summary");
sb.AppendLine("---|---");
Expand All @@ -46,7 +46,7 @@ public void Test_API_Plot()
sb.AppendLine($"[**{mi.Name}**](#{mi.Name})|{summary}");
}

//
// table of AddPlottable() methods
sb.AppendLine("### Shortcuts for Adding Plottables");
sb.AppendLine("Method | Summary");
sb.AppendLine("---|---");
Expand Down

0 comments on commit b778947

Please sign in to comment.