Public Access
234 lines
7.1 KiB
C#
234 lines
7.1 KiB
C#
#if WINDOWS
|
|
using Aprillz.MewUI;
|
|
using Aprillz.MewUI.Controls;
|
|
|
|
namespace MeetingAssistant.Workflow;
|
|
|
|
internal static class WorkflowRulesEditorMarkdownRenderer
|
|
{
|
|
public static UIElement CreateContent(string content)
|
|
{
|
|
var panel = new StackPanel()
|
|
.Vertical()
|
|
.Spacing(7);
|
|
foreach (var block in WorkflowRulesEditorMarkdown.Parse(content))
|
|
{
|
|
panel.Add(block switch
|
|
{
|
|
WorkflowRulesEditorMarkdownCodeBlock codeBlock => CreateCodeBlock(codeBlock),
|
|
WorkflowRulesEditorMarkdownTable table => CreateTable(table),
|
|
WorkflowRulesEditorMarkdownParagraph paragraph => CreateParagraph(paragraph),
|
|
_ => new TextBlock()
|
|
});
|
|
}
|
|
|
|
return panel;
|
|
}
|
|
|
|
private static UIElement CreateParagraph(WorkflowRulesEditorMarkdownParagraph paragraph)
|
|
{
|
|
var lines = SplitInlineLines(paragraph.Inlines);
|
|
if (lines.Count == 1)
|
|
{
|
|
return CreateParagraphLine(lines[0]);
|
|
}
|
|
|
|
var panel = new StackPanel()
|
|
.Vertical()
|
|
.Spacing(3);
|
|
foreach (var line in lines)
|
|
{
|
|
panel.Add(CreateParagraphLine(line));
|
|
}
|
|
|
|
return panel;
|
|
}
|
|
|
|
private static UIElement CreateParagraphLine(IReadOnlyList<WorkflowRulesEditorMarkdownInline> inlines)
|
|
{
|
|
var linePanel = new WrapPanel()
|
|
.Spacing(1);
|
|
foreach (var inline in inlines)
|
|
{
|
|
foreach (var element in CreateInlineElements(inline))
|
|
{
|
|
linePanel.Add(element);
|
|
}
|
|
}
|
|
|
|
return linePanel;
|
|
}
|
|
|
|
private static IEnumerable<UIElement> CreateInlineElements(WorkflowRulesEditorMarkdownInline inline)
|
|
{
|
|
if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Code)
|
|
{
|
|
yield return CreateInlineCode(inline.Text);
|
|
yield break;
|
|
}
|
|
|
|
foreach (var token in SplitInlineText(inline.Text))
|
|
{
|
|
var text = new TextBlock()
|
|
.Text(token)
|
|
.TextWrapping(TextWrapping.Wrap)
|
|
.Foreground(Color.FromRgb(230, 235, 243));
|
|
if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Bold)
|
|
{
|
|
text.FontWeight(FontWeight.Bold);
|
|
}
|
|
else if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Italic)
|
|
{
|
|
text.FontFamily("Segoe UI Italic");
|
|
}
|
|
|
|
yield return text;
|
|
}
|
|
}
|
|
|
|
private static IReadOnlyList<IReadOnlyList<WorkflowRulesEditorMarkdownInline>> SplitInlineLines(
|
|
IReadOnlyList<WorkflowRulesEditorMarkdownInline> inlines)
|
|
{
|
|
var lines = new List<IReadOnlyList<WorkflowRulesEditorMarkdownInline>>();
|
|
var current = new List<WorkflowRulesEditorMarkdownInline>();
|
|
foreach (var inline in inlines)
|
|
{
|
|
var parts = inline.Text.Split('\n');
|
|
for (var index = 0; index < parts.Length; index++)
|
|
{
|
|
if (parts[index].Length > 0)
|
|
{
|
|
current.Add(inline with { Text = parts[index] });
|
|
}
|
|
|
|
if (index < parts.Length - 1)
|
|
{
|
|
lines.Add(current);
|
|
current = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
lines.Add(current);
|
|
return lines;
|
|
}
|
|
|
|
private static UIElement CreateInlineCode(string text)
|
|
{
|
|
return new Border()
|
|
.Padding(4, 1, 4, 2)
|
|
.Margin(1, 0, 1, 0)
|
|
.CornerRadius(4)
|
|
.BorderThickness(1)
|
|
.BorderBrush(Color.FromRgb(86, 94, 108))
|
|
.Background(Color.FromRgb(24, 28, 35))
|
|
.Child(new TextBlock()
|
|
.Text(text)
|
|
.FontFamily("Consolas")
|
|
.Foreground(Color.FromRgb(237, 241, 247)));
|
|
}
|
|
|
|
private static UIElement CreateTable(WorkflowRulesEditorMarkdownTable table)
|
|
{
|
|
var rows = table.Rows
|
|
.Select(row => new MarkdownTableRow(PadCells(row, table.Header.Count)))
|
|
.ToArray();
|
|
var gridView = new GridView()
|
|
.HeaderHeight(30)
|
|
.RowHeight(30)
|
|
.CellPadding(new Thickness(8, 4, 8, 4))
|
|
.ShowGridLines(true)
|
|
.ZebraStriping(true);
|
|
|
|
for (var index = 0; index < table.Header.Count; index++)
|
|
{
|
|
var columnIndex = index;
|
|
gridView.AddColumn<MarkdownTableRow>(
|
|
table.Header[index],
|
|
GetMarkdownTableColumnWidth(table, index),
|
|
_ => new TextBlock()
|
|
.TextWrapping(TextWrapping.NoWrap)
|
|
.Foreground(Color.FromRgb(230, 235, 243)),
|
|
(element, row, _, _) => ((TextBlock)element).Text(row.GetCell(columnIndex)),
|
|
minWidth: 64,
|
|
resizable: true);
|
|
}
|
|
|
|
return gridView
|
|
.ItemsSource(rows)
|
|
.MinWidth(Math.Min(900, table.Header.Count * 120))
|
|
.Height(Math.Min(420, 30 + Math.Max(1, rows.Length) * 30));
|
|
}
|
|
|
|
private static UIElement CreateCodeBlock(WorkflowRulesEditorMarkdownCodeBlock codeBlock)
|
|
{
|
|
return new Border()
|
|
.Padding(9)
|
|
.CornerRadius(6)
|
|
.BorderThickness(1)
|
|
.BorderBrush(Color.FromRgb(86, 94, 108))
|
|
.Background(Color.FromRgb(20, 24, 31))
|
|
.Child(new TextBlock()
|
|
.Text(codeBlock.Text)
|
|
.TextWrapping(TextWrapping.Wrap)
|
|
.FontFamily("Consolas")
|
|
.Foreground(Color.FromRgb(237, 241, 247)));
|
|
}
|
|
|
|
private static IEnumerable<string> SplitInlineText(string text)
|
|
{
|
|
var start = 0;
|
|
while (start < text.Length)
|
|
{
|
|
var end = start;
|
|
var isWhitespace = char.IsWhiteSpace(text[start]);
|
|
while (end < text.Length && char.IsWhiteSpace(text[end]) == isWhitespace)
|
|
{
|
|
end++;
|
|
}
|
|
|
|
var token = text[start..end];
|
|
if (token.Length > 0)
|
|
{
|
|
yield return token;
|
|
}
|
|
|
|
start = end;
|
|
}
|
|
}
|
|
|
|
private static IReadOnlyList<string> PadCells(IReadOnlyList<string> cells, int count)
|
|
{
|
|
if (cells.Count >= count)
|
|
{
|
|
return cells;
|
|
}
|
|
|
|
return cells
|
|
.Concat(Enumerable.Repeat("", count - cells.Count))
|
|
.ToArray();
|
|
}
|
|
|
|
private static double GetMarkdownTableColumnWidth(
|
|
WorkflowRulesEditorMarkdownTable table,
|
|
int index)
|
|
{
|
|
var maxLength = new[] { table.Header[index].Length }
|
|
.Concat(table.Rows.Select(row => index < row.Count ? row[index].Length : 0))
|
|
.DefaultIfEmpty(0)
|
|
.Max();
|
|
return Math.Clamp(maxLength * 8 + 28, 72, 260);
|
|
}
|
|
|
|
private sealed record MarkdownTableRow(IReadOnlyList<string> Cells)
|
|
{
|
|
public string GetCell(int index)
|
|
{
|
|
return index >= 0 && index < Cells.Count
|
|
? Cells[index]
|
|
: "";
|
|
}
|
|
}
|
|
}
|
|
#endif
|