Switch store embeds to use DataTablePrettyPrinter
This commit is contained in:
parent
5787961270
commit
3ee9e5322a
@ -3,11 +3,9 @@ module Degenz.Bot
|
|||||||
open System.IO
|
open System.IO
|
||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
open DSharpPlus.Entities
|
|
||||||
open DSharpPlus.SlashCommands
|
open DSharpPlus.SlashCommands
|
||||||
open Degenz
|
open Degenz
|
||||||
open Emzi0767.Utilities
|
open Emzi0767.Utilities
|
||||||
open Degenz.SlotMachine
|
|
||||||
|
|
||||||
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
|
type EmptyGlobalCommandToAvoidFamousDuplicateSlashCommandsBug() = inherit ApplicationCommandModule ()
|
||||||
|
|
||||||
|
@ -76,5 +76,8 @@
|
|||||||
<!-- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>-->
|
<!-- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>-->
|
||||||
<!-- </Content>-->
|
<!-- </Content>-->
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DataTablePrettyPrinter\DataTablePrettyPrinter.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="..\.paket\Paket.Restore.targets" />
|
<Import Project="..\.paket\Paket.Restore.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
module Degenz.Store
|
module Degenz.Store
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Data
|
||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open DSharpPlus.Entities
|
open DSharpPlus.Entities
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
@ -9,6 +10,7 @@ open DSharpPlus.SlashCommands
|
|||||||
open Degenz
|
open Degenz
|
||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
open Degenz.PlayerInteractions
|
open Degenz.PlayerInteractions
|
||||||
|
open DataTablePrettyPrinter
|
||||||
|
|
||||||
let checkHasStock (item : StoreItem) player =
|
let checkHasStock (item : StoreItem) player =
|
||||||
if item.Stock > 0 || item.LimitStock = false
|
if item.Stock > 0 || item.LimitStock = false
|
||||||
@ -53,24 +55,28 @@ let getItemEmbeds owned (items : StoreItem list) =
|
|||||||
|> List.map (fun (id,count) -> items |> List.find (fun i -> i.Item.Id = id) , count )
|
|> List.map (fun (id,count) -> items |> List.find (fun i -> i.Item.Id = id) , count )
|
||||||
|> List.map (fun (item,count) ->
|
|> List.map (fun (item,count) ->
|
||||||
let embed = DiscordEmbedBuilder()
|
let embed = DiscordEmbedBuilder()
|
||||||
|
use table = new DataTable()
|
||||||
|
table.SetBorder(Border.None)
|
||||||
|
table.SetShowTableName(false)
|
||||||
|
let values : ResizeArray<string * string> = ResizeArray()
|
||||||
if not owned && item.LimitStock then
|
if not owned && item.LimitStock then
|
||||||
embed.AddField("Stock", $"{item.Stock}", true) |> ignore
|
values.Add("Stock", $"{item.Stock}")
|
||||||
item.Item.Attributes
|
item.Item.Attributes
|
||||||
|> List.iter (function
|
|> List.iter (function
|
||||||
| Buyable price -> embed.AddField("Price 💰", (if price = 0<GBT> then "Free" else $"{price} $GBT"), true) |> ignore
|
| Buyable price ->
|
||||||
|
values.Add("Price 💰", (if price = 0<GBT> then "Free" else $"{price} $GBT"))
|
||||||
| Attackable power ->
|
| Attackable power ->
|
||||||
let title = match item.Item.Type with ItemType.Hack -> "$GBT Reward" | _ -> "Power"
|
let title = match item.Item.Type with ItemType.Hack -> "$GBT Reward" | _ -> "Power"
|
||||||
embed.AddField($"{title} |", string power, true) |> ignore
|
values.Add($"{title}", string power)
|
||||||
| RateLimitable time ->
|
| RateLimitable time ->
|
||||||
let title = match item.Item.Type with ItemType.Hack -> "Cooldown" | ItemType.Shield -> "Active For" | _ -> "Expires"
|
let title = match item.Item.Type with ItemType.Hack -> "Cooldown" | ItemType.Shield -> "Active For" | _ -> "Expires"
|
||||||
let ts = TimeSpan.FromMinutes(int time)
|
let ts = TimeSpan.FromMinutes(int time)
|
||||||
let timeStr = if ts.Hours = 0 then $"{ts.Minutes} mins" else $"{ts.Hours} hours"
|
let timeStr = if ts.Hours = 0 then $"{ts.Minutes} mins" else $"{ts.Hours} hours"
|
||||||
embed.AddField($"{title} |", timeStr, true) |> ignore
|
values.Add($"{title}", timeStr)
|
||||||
| Stackable max ->
|
| Stackable max ->
|
||||||
if owned then
|
if owned
|
||||||
embed.AddField($"Total Owned |", $"{count}", true) |> ignore
|
then values.Add($"Total Owned", $"{count}")
|
||||||
else
|
else values.Add($"Max Allowed", $"{max}")
|
||||||
embed.AddField($"Max Allowed |", $"{max}", true) |> ignore
|
|
||||||
| Modifiable effects ->
|
| Modifiable effects ->
|
||||||
let fx =
|
let fx =
|
||||||
effects
|
effects
|
||||||
@ -83,10 +89,23 @@ let getItemEmbeds owned (items : StoreItem list) =
|
|||||||
$"{f.TargetStat} {str} + {i}"
|
$"{f.TargetStat} {str} + {i}"
|
||||||
| RateMultiplier i -> $"{f.TargetStat} Multiplier - i")
|
| RateMultiplier i -> $"{f.TargetStat} Multiplier - i")
|
||||||
|> String.concat "\n"
|
|> String.concat "\n"
|
||||||
embed.AddField($"Effect - Amount ", $"{fx}", true) |> ignore
|
values.Add($"Effect - Amount", $"{fx}")
|
||||||
| _ -> ())
|
| _ -> ())
|
||||||
|
for title , _ in values do
|
||||||
|
let column = table.Columns.Add(title)
|
||||||
|
column.SetWidth(40 / values.Count)
|
||||||
|
column.SetDataAlignment(TextAlignment.Center)
|
||||||
|
column.SetHeaderBorder(Border.Bottom)
|
||||||
|
column.SetDataBorder(Border.Top)
|
||||||
|
|
||||||
|
let arr : obj array = values |> Seq.map snd |> Seq.cast<obj> |> Seq.toArray
|
||||||
|
table.Rows.Add(arr) |> ignore
|
||||||
|
|
||||||
|
let split = table.ToPrettyPrintedString().Split("\n")
|
||||||
|
let text = split |> Array.skip 1 |> Array.take (split.Length - 3) |> String.concat "\n"
|
||||||
embed
|
embed
|
||||||
.WithColor(WeaponClass.getClassEmbedColor item.Item)
|
.WithColor(WeaponClass.getClassEmbedColor item.Item)
|
||||||
|
.WithDescription($"```{text}```")
|
||||||
.WithTitle($"{item.Item.Name}")
|
.WithTitle($"{item.Item.Name}")
|
||||||
|> ignore
|
|> ignore
|
||||||
if String.IsNullOrWhiteSpace(item.Item.IconUrl)
|
if String.IsNullOrWhiteSpace(item.Item.IconUrl)
|
||||||
|
@ -4,4 +4,4 @@ DSharpPlus.Interactivity
|
|||||||
DSharpPlus.SlashCommands
|
DSharpPlus.SlashCommands
|
||||||
dotenv.net
|
dotenv.net
|
||||||
Npgsql.FSharp
|
Npgsql.FSharp
|
||||||
mixpanel-csharp
|
mixpanel-csharp
|
43
DataTablePrettyPrinter/Border.cs
Normal file
43
DataTablePrettyPrinter/Border.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerates the border flags of the text represented by a <see cref="DataTable"/> which is to be drawn on a
|
||||||
|
/// pretty printed string.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum Border
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No border.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bottom border.
|
||||||
|
/// </summary>
|
||||||
|
Bottom = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Left border.
|
||||||
|
/// </summary>
|
||||||
|
Left = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Right border.
|
||||||
|
/// </summary>
|
||||||
|
Right = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Top border.
|
||||||
|
/// </summary>
|
||||||
|
Top = 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All borders.
|
||||||
|
/// </summary>
|
||||||
|
All = 15,
|
||||||
|
}
|
||||||
|
}
|
213
DataTablePrettyPrinter/CharExtensions.cs
Normal file
213
DataTablePrettyPrinter/CharExtensions.cs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An extension class providing <see cref="char"/> utility methods for pretty printing to a string.
|
||||||
|
/// </summary>
|
||||||
|
internal static class CharExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a border on a canvas given a bounding box specified by coordinates.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="canvas">
|
||||||
|
/// The canvas to draw on which is assumed to be large enough.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x1">
|
||||||
|
/// The x coordinate of the beginning of the bounding box to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y1">
|
||||||
|
/// The y coordinate of the beginning of the bounding box to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x2">
|
||||||
|
/// The x coordinate of the end of the bounding box to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y2">
|
||||||
|
/// The y coordinate of the end of the bounding box to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="border">
|
||||||
|
/// The border flags which dictate which border to draw.
|
||||||
|
/// </param>
|
||||||
|
internal static void DrawBorder(this char[,] canvas, int x1, int y1, int x2, int y2, Border border)
|
||||||
|
{
|
||||||
|
if (border.HasFlag(Border.Top))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(x1, y1, x2, y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (border.HasFlag(Border.Bottom))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(x1, y2, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (border.HasFlag(Border.Left))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(x1, y1, x1, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (border.HasFlag(Border.Right))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(x2, y1, x2, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a line on a canvas given a beginning and an end coordinate.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="canvas">
|
||||||
|
/// The canvas to draw on which is assumed to be large enough.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x1">
|
||||||
|
/// The x coordinate of the beginning of the line to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y1">
|
||||||
|
/// The y coordinate of the beginning of the line to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x2">
|
||||||
|
/// The x coordinate of the end of the line to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y2">
|
||||||
|
/// The y coordinate of the end of the line to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// If this line crosses any other line drawn on the canvas then a '+' is inserted on the crossing boundary.
|
||||||
|
/// </remarks>
|
||||||
|
///
|
||||||
|
/// <exception cref="ArgumentException">
|
||||||
|
/// Thrown when the line is neither horizontal nor vertical.
|
||||||
|
/// </exception>
|
||||||
|
internal static void DrawLine(this char[,] canvas, int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
if (x1 != x2 && y1 != y2)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Cannot draw non-horizontal or non-vertical lines");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x1 == x2)
|
||||||
|
{
|
||||||
|
if (y1 > y2)
|
||||||
|
{
|
||||||
|
Utilities.Swap(ref y1, ref y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y = y1; y <= y2; ++y)
|
||||||
|
{
|
||||||
|
canvas[y, x1] = (y == y1 || y == y2 || canvas[y, x1] == '─' || canvas[y, x1] == '+') ? '+' : '|';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x1 > x2)
|
||||||
|
{
|
||||||
|
Utilities.Swap(ref x1, ref x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var x = x1; x <= x2; ++x)
|
||||||
|
{
|
||||||
|
canvas[y1, x] = (x == x1 || x == x2 || canvas[y1, x] == '|' || canvas[y1, x] == '+') ? ' ' : '─';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a string on a canvas with alignment specified.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="canvas">
|
||||||
|
/// The canvas to draw on which is assumed to be large enough.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x1">
|
||||||
|
/// The x coordinate of the beginning of the string to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y1">
|
||||||
|
/// The y coordinate of the beginning of the string to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="x2">
|
||||||
|
/// The x coordinate of the end of the string to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y2">
|
||||||
|
/// The y coordinate of the end of the string to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="text">
|
||||||
|
/// The text to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="alignment">
|
||||||
|
/// The alignment of the <paramref name="text"/> to draw.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <remarks>
|
||||||
|
/// If the text cannot be contained within the bounding box specified by the coordinates then either nothing is
|
||||||
|
/// drawn or the input string is truncated and '..' is added to the end.
|
||||||
|
/// </remarks>
|
||||||
|
internal static void DrawText(this char[,] canvas, int x1, int y1, int x2, int y2, string text, TextAlignment alignment)
|
||||||
|
{
|
||||||
|
// Truncate the text if it will not fit in the text box bounds
|
||||||
|
if (text.Length > x2 - x1 + 1)
|
||||||
|
{
|
||||||
|
if (x2 - x1 >= 1)
|
||||||
|
{
|
||||||
|
text = text.Substring(0, x2 - x1 - 1) + "..";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the coordinates based the text alignment
|
||||||
|
switch (alignment)
|
||||||
|
{
|
||||||
|
case TextAlignment.Center:
|
||||||
|
{
|
||||||
|
y1 = (y2 + y1) / 2;
|
||||||
|
x1 += (x2 - x1 + 1 - text.Length) / 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TextAlignment.Left:
|
||||||
|
{
|
||||||
|
y1 = (y2 + y1) / 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TextAlignment.Right:
|
||||||
|
{
|
||||||
|
y1 = (y2 + y1) / 2;
|
||||||
|
x1 = x2 - text.Length + 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Unreachable case reached");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var x = x1; x < x1 + text.Length; ++x)
|
||||||
|
{
|
||||||
|
canvas[y1, x] = text[x - x1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
403
DataTablePrettyPrinter/DataColumnExtensions.cs
Normal file
403
DataTablePrettyPrinter/DataColumnExtensions.cs
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An extension class providing <see cref="DataColumn"/> utility methods for pretty printing to a string.
|
||||||
|
/// </summary>
|
||||||
|
public static class DataColumnExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the border around the data area of the column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The border around the data area of the column.
|
||||||
|
/// </returns>
|
||||||
|
public static Border GetDataBorder(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty("DataBorder", Border.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the border around the data area of the column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetDataBorder(this DataColumn column, Border value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("DataBorder", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text alignment of the data in this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// Gets the data alignment.
|
||||||
|
/// </returns>
|
||||||
|
public static TextAlignment GetDataAlignment(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty("DataAlignment", TextAlignment.Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the text alignment of the data in this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetDataAlignment(this DataColumn column, TextAlignment value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("DataAlignment", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the formatting method which given a column and row formats the data of the cell into a string. This
|
||||||
|
/// API can be used for arbitrary formatting of induvidual data cells.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The method which formats the data cell.
|
||||||
|
/// </returns>
|
||||||
|
public static Func<DataColumn, DataRow, string> GetDataTextFormat(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty<Func<DataColumn, DataRow, string>>("DataTextFormat", (c, r) => string.Format("{0}", r[c]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the formatting method which given a column and row formats the data of the cell into a string. This
|
||||||
|
/// API can be used for arbitrary formatting of induvidual data cells.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The method used to format the data cell which will be called during pretty printing of the table.
|
||||||
|
/// </param>
|
||||||
|
public static void SetDataTextFormat(this DataColumn column, Func<DataColumn, DataRow, string> value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("DataTextFormat", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the border around the column header area which displays the column names.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The border around the column header area.
|
||||||
|
/// </returns>
|
||||||
|
public static Border GetHeaderBorder(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty("HeaderBorder", Border.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the border around the column header area which displays the column names.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetHeaderBorder(this DataColumn column, Border value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("HeaderBorder", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="DataColumn.ColumnName"/> text alignment.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// Gets the column name text alignment.
|
||||||
|
/// </returns>
|
||||||
|
public static TextAlignment GetColumnNameAlignment(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty("ColumnNameAlignment", TextAlignment.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the <see cref="DataColumn.ColumnName"/> text alignment.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetColumnNameAlignment(this DataColumn column, TextAlignment value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("ColumnNameAlignment", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether to show the <see cref="DataTable.TableName"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> if the column name is to be shown; <c>false</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static bool GetShowColumnName(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetExtendedProperty("ShowColumnName", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets whether to show the <see cref="DataTable.TableName"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetShowColumnName(this DataColumn column, bool value)
|
||||||
|
{
|
||||||
|
column.SetExtendedProperty("ShowColumnName", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the width (in characters) of this column as it would appear on the pretty printed table.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The width (in characters) of this column which is retrieved either by user defined value or the aggregate
|
||||||
|
/// maximum width of any row in the table.
|
||||||
|
/// </returns>
|
||||||
|
public static int GetWidth(this DataColumn column)
|
||||||
|
{
|
||||||
|
if (column.ExtendedProperties.ContainsKey("Width"))
|
||||||
|
{
|
||||||
|
return (int)column.ExtendedProperties["Width"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var columnNameLength = 1;
|
||||||
|
|
||||||
|
if (column.GetShowColumnName())
|
||||||
|
{
|
||||||
|
columnNameLength = column.ColumnName.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Linq.Max cannot handle empty sequences
|
||||||
|
if (column.Table.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
return columnNameLength + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Math.Max(columnNameLength, column.Table.Rows.Cast<DataRow>().Max(r => column.GetDataTextFormat().Invoke(column, r).Length)) + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the width (in characters) of this column as it would appear on the pretty printed table.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set which will be clamped to be at least 1.
|
||||||
|
/// </param>
|
||||||
|
public static void SetWidth(this DataColumn column, int value)
|
||||||
|
{
|
||||||
|
value = Math.Max(1, value);
|
||||||
|
|
||||||
|
column.SetExtendedProperty("Width", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the beginning X coordinate of the data area of this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The X coordinate of the beginning of the data area.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetDataX1(this DataColumn column)
|
||||||
|
{
|
||||||
|
var columnIndex = column.Table.Columns.IndexOf(column);
|
||||||
|
|
||||||
|
return column.Table.Columns.Cast<DataColumn>().Take(columnIndex).Aggregate(0, (a, c) => a + c.GetWidth() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the end X coordinate of the data area of this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The X coordinate of the end of the data area.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetDataX2(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetDataX1() + 1 + column.GetWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the beginning Y coordinate of the data area of this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The Y coordinate of the beginning of the data area.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetDataY1(this DataColumn column)
|
||||||
|
{
|
||||||
|
// Account for the top border
|
||||||
|
var y1 = 1;
|
||||||
|
|
||||||
|
// Account for the title and a rule following the title
|
||||||
|
if (column.Table.GetShowTableName())
|
||||||
|
{
|
||||||
|
y1 += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account for the header and a rule following the header
|
||||||
|
if (column.Table.GetShowColumnHeader())
|
||||||
|
{
|
||||||
|
y1 += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the end Y coordinate of the data area of this column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The input column.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The Y coordinate of the end of the data area.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetDataY2(this DataColumn column)
|
||||||
|
{
|
||||||
|
return column.GetDataY1() + column.Table.Rows.Cast<DataRow>().Aggregate(0, (a, r) => a + r.GetHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an extended property from the <see cref="DataColumn"/> with a default value if it does not exist.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// The type of the value to get.
|
||||||
|
/// </typeparam>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="property">
|
||||||
|
/// The extended property to get.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="defaultValue">
|
||||||
|
/// The default value to return if the extended property does not exist.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The value of the extended property if it exists; <paramref name="defaultValue"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
internal static T GetExtendedProperty<T>(this DataColumn column, string property, T defaultValue = default)
|
||||||
|
{
|
||||||
|
if (column.ExtendedProperties[property] is T)
|
||||||
|
{
|
||||||
|
return (T)column.ExtendedProperties[property];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets an extended property from the <see cref="DataColumn"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// The type of the value to get.
|
||||||
|
/// </typeparam>
|
||||||
|
///
|
||||||
|
/// <param name="column">
|
||||||
|
/// The column to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="property">
|
||||||
|
/// The extended property to set.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
internal static void SetExtendedProperty<T>(this DataColumn column, string property, T value)
|
||||||
|
{
|
||||||
|
column.ExtendedProperties[property] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
DataTablePrettyPrinter/DataRowExtensions.cs
Normal file
46
DataTablePrettyPrinter/DataRowExtensions.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An extension class providing <see cref="DataRow"/> utility methods for pretty printing to a string.
|
||||||
|
/// </summary>
|
||||||
|
internal static class DataRowExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the width (in characters) of this row as it would appear on the pretty printed table by aggregating
|
||||||
|
/// the widths of each individual column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="row">
|
||||||
|
/// The input row.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The width (in characters) of this row.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetWidth(this DataRow row)
|
||||||
|
{
|
||||||
|
return row.Table.Columns.Cast<DataColumn>().Aggregate(0, (a, c) => a + c.GetWidth() + 1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the height (in characters) of this row as it would appear on the pretty printed table by aggregating
|
||||||
|
/// the heights of each individual column.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="row">
|
||||||
|
/// The input row.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The height (in characters) of this row.
|
||||||
|
/// </returns>
|
||||||
|
internal static int GetHeight(this DataRow row)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
308
DataTablePrettyPrinter/DataTableExtensions.cs
Normal file
308
DataTablePrettyPrinter/DataTableExtensions.cs
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An extension class providing <see cref="DataTable"/> utility methods for pretty printing to a string.
|
||||||
|
/// </summary>
|
||||||
|
public static class DataTableExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the border around the entire table.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The border around the entire table.
|
||||||
|
/// </returns>
|
||||||
|
public static Border GetBorder(this DataTable table)
|
||||||
|
{
|
||||||
|
return table.GetExtendedProperty("Border", Border.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the border around the entire table.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetBorder(this DataTable table, Border value)
|
||||||
|
{
|
||||||
|
table.SetExtendedProperty("Border", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether to show the column header section which shows the column names.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> if the column header is to be shown; <c>false</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static bool GetShowColumnHeader(this DataTable table)
|
||||||
|
{
|
||||||
|
return table.GetExtendedProperty("ShowColumnHeader", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets whether to show the column header section which shows the column names.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetShowColumnHeader(this DataTable table, bool value)
|
||||||
|
{
|
||||||
|
table.SetExtendedProperty("ShowColumnHeader", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether to show the <see cref="DataTable.TableName"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> if the table title is to be shown; <c>false</c> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
public static bool GetShowTableName(this DataTable table)
|
||||||
|
{
|
||||||
|
return table.GetExtendedProperty("ShowTableName", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets whether to show the <see cref="DataTable.TableName"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetShowTableName(this DataTable table, bool value)
|
||||||
|
{
|
||||||
|
table.SetExtendedProperty("ShowTableName", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text alignment of the title determined by the <see cref="DataTable.TableName"/> property.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// Gets the title text alignment.
|
||||||
|
/// </returns>
|
||||||
|
public static TextAlignment GetTitleTextAlignment(this DataTable table)
|
||||||
|
{
|
||||||
|
return table.GetExtendedProperty("TitleTextAlignment", TextAlignment.Center);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the text alignment of the title determined by the <see cref="DataTable.TableName"/> property.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
public static void SetTitleTextAlignment(this DataTable table, TextAlignment value)
|
||||||
|
{
|
||||||
|
table.SetExtendedProperty("TitleTextAlignment", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the <see cref="DataTable"/> into pretty printed string which can be displayed on the console.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The pretty printed table.
|
||||||
|
/// </returns>
|
||||||
|
public static string ToPrettyPrintedString(this DataTable table)
|
||||||
|
{
|
||||||
|
int x2 = table.Columns.Cast<DataColumn>().Last().GetDataX2();
|
||||||
|
int y2 = table.Columns.Cast<DataColumn>().Last().GetDataY2();
|
||||||
|
|
||||||
|
char[] newLineChars = Environment.NewLine.ToCharArray();
|
||||||
|
char[,] canvas = new char[y2 + 1, x2 + 1 + newLineChars.Length];
|
||||||
|
|
||||||
|
// Fill the table with spaces and new lines at the end of each row
|
||||||
|
for (var y = 0; y < y2 + 1; ++y)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < x2 + 1; ++x)
|
||||||
|
{
|
||||||
|
canvas[y, x] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < newLineChars.Length; ++i)
|
||||||
|
{
|
||||||
|
canvas[y, x2 + 1 + i] = newLineChars[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the table border
|
||||||
|
canvas.DrawBorder(0, 0, x2, y2, table.GetBorder());
|
||||||
|
|
||||||
|
// Keep track of the x and y coordinates we are drawing on
|
||||||
|
int x1 = 0;
|
||||||
|
int y1 = 0;
|
||||||
|
|
||||||
|
if (table.GetShowTableName())
|
||||||
|
{
|
||||||
|
++y1;
|
||||||
|
|
||||||
|
var titleAlignment = table.GetTitleTextAlignment();
|
||||||
|
canvas.DrawText(2, y1, x2 - 2, y1, table.TableName, titleAlignment);
|
||||||
|
|
||||||
|
++y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the column widths for performance
|
||||||
|
var cachedColumnWidths = table.Columns.Cast<DataColumn>().Select(c => c.GetWidth()).ToList();
|
||||||
|
|
||||||
|
if (table.GetShowColumnHeader())
|
||||||
|
{
|
||||||
|
x1 = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < table.Columns.Count; ++i)
|
||||||
|
{
|
||||||
|
// Draw the header border
|
||||||
|
canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + 2, table.Columns[i].GetHeaderBorder());
|
||||||
|
|
||||||
|
if (table.Columns[i].GetShowColumnName())
|
||||||
|
{
|
||||||
|
// Draw the header name
|
||||||
|
canvas.DrawText(x1 + 2, y1 + 1, x1 + 1 + cachedColumnWidths[i] - 2, y1 + 1, table.Columns[i].ColumnName, table.Columns[i].GetColumnNameAlignment());
|
||||||
|
}
|
||||||
|
|
||||||
|
x1 += cachedColumnWidths[i] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
y1 += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
x1 = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < table.Columns.Count; ++i)
|
||||||
|
{
|
||||||
|
// Draw the data border
|
||||||
|
canvas.DrawBorder(x1, y1, x1 + cachedColumnWidths[i] + 1, y1 + table.Rows.Count + 1, table.Columns[i].GetDataBorder());
|
||||||
|
|
||||||
|
x1 += cachedColumnWidths[i] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++y1;
|
||||||
|
|
||||||
|
for (var i = 0; i < table.Rows.Count; ++i)
|
||||||
|
{
|
||||||
|
x1 = 2;
|
||||||
|
|
||||||
|
for (var j = 0; j < table.Columns.Count; ++j)
|
||||||
|
{
|
||||||
|
var dataText = table.Columns[j].GetDataTextFormat().Invoke(table.Columns[j], table.Rows[i]);
|
||||||
|
|
||||||
|
// Draw the cell text
|
||||||
|
canvas.DrawText(x1, y1, x1 + cachedColumnWidths[j] - 3, y1, dataText, table.Columns[j].GetDataAlignment());
|
||||||
|
|
||||||
|
x1 += cachedColumnWidths[j] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer = new char[canvas.GetLength(0) * canvas.GetLength(1)];
|
||||||
|
Buffer.BlockCopy(canvas, 0, buffer, 0, buffer.Length * sizeof(char));
|
||||||
|
|
||||||
|
return new string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an extended property from the <see cref="DataTable"/> with a default value if it does not exist.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// The type of the value to get.
|
||||||
|
/// </typeparam>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="property">
|
||||||
|
/// The extended property to get.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="defaultValue">
|
||||||
|
/// The default value to return if the extended property does not exist.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <returns>
|
||||||
|
/// The value of the extended property if it exists; <paramref name="defaultValue"/> otherwise.
|
||||||
|
/// </returns>
|
||||||
|
internal static T GetExtendedProperty<T>(this DataTable table, string property, T defaultValue = default)
|
||||||
|
{
|
||||||
|
if (table.ExtendedProperties[property] is T)
|
||||||
|
{
|
||||||
|
return (T)table.ExtendedProperties[property];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets an extended property from the <see cref="DataTable"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// The type of the value to get.
|
||||||
|
/// </typeparam>
|
||||||
|
///
|
||||||
|
/// <param name="table">
|
||||||
|
/// The table to pretty print.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="property">
|
||||||
|
/// The extended property to set.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="value">
|
||||||
|
/// The value to set.
|
||||||
|
/// </param>
|
||||||
|
internal static void SetExtendedProperty<T>(this DataTable table, string property, T value)
|
||||||
|
{
|
||||||
|
table.ExtendedProperties[property] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
DataTablePrettyPrinter/DataTablePrettyPrinter.csproj
Normal file
25
DataTablePrettyPrinter/DataTablePrettyPrinter.csproj
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<Authors>Filip Jeremic</Authors>
|
||||||
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
|
<Description>An extension library of System.Data.DataTable which provides extension methods for fully customizable pretty-printing of DataTable to an ASCII formatted string which can be displayed on the console or any text buffer.</Description>
|
||||||
|
<PackageProjectUrl>https://github.com/fjeremic/DataTablePrettyPrinter</PackageProjectUrl>
|
||||||
|
<RepositoryUrl>https://github.com/fjeremic/DataTablePrettyPrinter</RepositoryUrl>
|
||||||
|
<RepositoryType>GitHub</RepositoryType>
|
||||||
|
<PackageTags>DataTable;Print;PrettyPrint;Pretty-Print;Console;SQL</PackageTags>
|
||||||
|
<Version>0.2.0</Version>
|
||||||
|
<PackageReleaseNotes>Release notes:
|
||||||
|
https://github.com/fjeremic/DataTablePrettyPrinter/releases</PackageReleaseNotes>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
11
DataTablePrettyPrinter/GlobalSuppressions.cs
Normal file
11
DataTablePrettyPrinter/GlobalSuppressions.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File should have header")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1404:Code analysis suppression should have justification")]
|
||||||
|
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines")]
|
26
DataTablePrettyPrinter/TextAlignment.cs
Normal file
26
DataTablePrettyPrinter/TextAlignment.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerates the alignment of the text represented by a <see cref="DataTable"/> which is to be pretty printing to
|
||||||
|
/// a string.
|
||||||
|
/// </summary>
|
||||||
|
public enum TextAlignment
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Text is centered.
|
||||||
|
/// </summary>
|
||||||
|
Center,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text is aligned to the left.
|
||||||
|
/// </summary>
|
||||||
|
Left,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text is aligned to the right.
|
||||||
|
/// </summary>
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
}
|
31
DataTablePrettyPrinter/Utilities.cs
Normal file
31
DataTablePrettyPrinter/Utilities.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
namespace DataTablePrettyPrinter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A utility class with miscellaneous methods.
|
||||||
|
/// </summary>
|
||||||
|
internal static class Utilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Swaps the values of <paramref name="x"/> and <paramref name="y"/>.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// The type of the values to swap.
|
||||||
|
/// </typeparam>
|
||||||
|
///
|
||||||
|
/// <param name="x">
|
||||||
|
/// The value to swap with <paramref name="y"/>.
|
||||||
|
/// </param>
|
||||||
|
///
|
||||||
|
/// <param name="y">
|
||||||
|
/// The value to swap with <paramref name="x"/>.
|
||||||
|
/// </param>
|
||||||
|
internal static void Swap<T>(ref T x, ref T y)
|
||||||
|
{
|
||||||
|
T z = x;
|
||||||
|
|
||||||
|
x = y;
|
||||||
|
y = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30114.105
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Bot", "Bot\Bot.fsproj", "{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}"
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Bot", "Bot\Bot.fsproj", "{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataTablePrettyPrinter", "DataTablePrettyPrinter\DataTablePrettyPrinter.csproj", "{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -18,5 +20,13 @@ Global
|
|||||||
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.Build.0 = Release|Any CPU
|
{FF9E58A6-1A1D-4DEC-B52D-265F215BF315}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{44151B85-0D17-4270-AD72-490A6D8D6290}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{44151B85-0D17-4270-AD72-490A6D8D6290}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{44151B85-0D17-4270-AD72-490A6D8D6290}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{44151B85-0D17-4270-AD72-490A6D8D6290}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4D5B1BBE-AF8E-4B60-BCBD-201A356B0C55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -12,4 +12,4 @@ nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01125
|
|||||||
nuget MongoDB.Driver
|
nuget MongoDB.Driver
|
||||||
nuget dotenv.net 3.1.1
|
nuget dotenv.net 3.1.1
|
||||||
nuget Npgsql.FSharp
|
nuget Npgsql.FSharp
|
||||||
nuget mixpanel-csharp 5.0.0
|
nuget mixpanel-csharp 5.0.0
|
Loading…
x
Reference in New Issue
Block a user