Merge pull request #5364 from jlewin/main

Markdig table renderer prototype
This commit is contained in:
Lars Brubaker 2022-08-30 14:38:37 -07:00 committed by GitHub
commit b382c64656
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 182 additions and 4 deletions

View file

@ -99,8 +99,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
this.workspace = workspace;
this.RowPadding = 0;
this.RowBoarder = new BorderDouble(0, 0, 0, 1);
this.RowBoarderColor = theme.GetBorderColor(50);
this.RowBorder = new BorderDouble(0, 0, 0, 1);
this.RowBorderColor = theme.GetBorderColor(50);
var openLibraryButton = CreateOpenLibraryButton(sceneContext, theme);

View file

@ -90,7 +90,7 @@ namespace Markdig.Renderers
ObjectRenderers.Add(new AggMatchingTextRenderer(theme));
// Extension renderers
//ObjectRenderers.Add(new AggTableRenderer());
ObjectRenderers.Add(new AggTableRenderer());
//ObjectRenderers.Add(new AggTaskListRenderer());
}

View file

@ -0,0 +1,126 @@
// Copyright (c) Nicolas Musset. All rights reserved.
// Copyright (c) 2022, John Lewin
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System;
using Markdig.Extensions.Tables;
using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
namespace Markdig.Renderers.Agg
{
public class AggTableRenderer : AggObjectRenderer<Table>
{
protected override void Write(AggRenderer renderer, Table table)
{
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
if (table == null) throw new ArgumentNullException(nameof(table));
var aggTable = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Fit,
VAnchor = VAnchor.Fit,
Margin = new BorderDouble(top: 12),
};
// TODO: Use Markdig parser data to drive column/cell widths
//foreach (var tableColumnDefinition in table.ColumnDefinitions)
// Width = (tableColumnDefinition?.Width ?? 0) != 0 ? tableColumnDefinition.Width : <or auto>
renderer.Push(aggTable);
foreach (var rowObj in table)
{
var row = (TableRow)rowObj;
var aggRow = new AggTableRow()
{
IsHeadingRow = row.IsHeader,
};
renderer.Push(aggRow);
if (row.IsHeader)
{
// Update to desired header row styling and/or moving into AggTableRow for consistency
aggRow.BackgroundColor = MatterHackers.MatterControl.AppContext.Theme.TabBarBackground;
}
for (var i = 0; i < row.Count; i++)
{
var cellObj = row[i];
var cell = (TableCell)cellObj;
// Fixed width cells just to get something initially on screen
var aggCellBox = new GuiWidget()
{
Width = 200,
Height = 25,
};
// TODO: Cell Width - implement next, might be easy to track and perform in AggTableRow
/* (Spec)
* If any line of the markdown source is longer than the column width (see --columns), then the
* table will take up the full text width and the cell contents will wrap, with the relative cell
* widths determined by the number of dashes in the line separating the table header from the table
* body. (For example ---|- would make the first column 3/4 and the second column 1/4 of the full
* text width.) On the other hand, if no lines are wider than column width, then cell contents will
* not be wrapped, and the cells will be sized to their contents.
*/
// Cell box above enforces boundaries, use flow for layout
var aggCellFlow = new FlowLayoutWidget()
{
HAnchor = HAnchor.Stretch,
};
if (table.ColumnDefinitions.Count > 0)
{
// TODO: Ideally we'd be driving column width from metadata rather than hard-coded
// See example below from WPF implementation
//
// Grab the column definition, or fall back to a default
var columnIndex = cell.ColumnIndex < 0 || cell.ColumnIndex >= table.ColumnDefinitions.Count
? i
: cell.ColumnIndex;
columnIndex = columnIndex >= table.ColumnDefinitions.Count ? table.ColumnDefinitions.Count - 1 : columnIndex;
// TODO: revise alignment via Agg types that produce aligned text
var columnDefinition = table.ColumnDefinitions[columnIndex];
var alignment = columnDefinition.Alignment;
if (alignment.HasValue)
{
switch (alignment)
{
case TableColumnAlign.Center:
aggCellFlow.HAnchor |= HAnchor.Center;
break;
case TableColumnAlign.Right:
aggCellFlow.HAnchor |= HAnchor.Right;
break;
case TableColumnAlign.Left:
aggCellFlow.HAnchor |= HAnchor.Left;
break;
}
}
}
renderer.Push(aggCellBox);
renderer.Push(aggCellFlow);
renderer.Write(cell);
renderer.Pop();
renderer.Pop();
}
// Pop row
renderer.Pop();
}
// Pop table
renderer.Pop();
}
}
}

View file

@ -0,0 +1,52 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// Copyright (c) 2022, John Lewin
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System.Linq;
using Markdig.Renderers.Agg.Inlines;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
public class AggTableRow: FlowLayoutWidget
{
public AggTableRow()
{
this.VAnchor = VAnchor.Fit;
this.Margin = new BorderDouble(3, 4, 0, 12);
// Hack to force content on-screen (seemingly not working when set late/after constructor)
VAnchor = VAnchor.Absolute;
Height = 25;
}
public bool IsHeadingRow { get; set; }
// Override AddChild to push styles to child elements when table rows are resolved to the tree
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
if (childToAdd is TextWidget textWidget)
{
// textWidget.TextColor = new Color("#036ac3");
if (this.IsHeadingRow)
{
textWidget.Bold = true;
}
}
else if (childToAdd is TextLinkX textLink)
{
foreach (var childTextWidget in childToAdd.Children.OfType<TextWidget>())
{
if (this.IsHeadingRow)
{
childTextWidget.Bold = true;
}
}
}
return base.AddChild(childToAdd, indexInChildrenList);
}
}
}

@ -1 +1 @@
Subproject commit c4f8114e2006faa32e6792f1a4d007ab2bbaed9a
Subproject commit 3be867c69f3fedc3dbee0874466743e75bc2062d