From f0dba3865f843908c789a6bd6a3b6caa3740faae Mon Sep 17 00:00:00 2001 From: John Lewin Date: Mon, 29 Aug 2022 00:47:01 -0700 Subject: [PATCH 1/2] Markdig table renderer prototype --- .../PartPreviewWindow/ViewToolBarControls.cs | 4 +- .../Utilities/MarkdigAgg/AggRenderer.cs | 2 +- .../Utilities/MarkdigAgg/AggTableRenderer.cs | 117 ++++++++++++++++++ .../Utilities/MarkdigAgg/TableHeadingRow.cs | 42 +++++++ Submodules/agg-sharp | 2 +- 5 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs create mode 100644 MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs diff --git a/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs b/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs index c294cf2f0..3b7536404 100644 --- a/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs +++ b/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs @@ -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); diff --git a/MatterControlLib/Utilities/MarkdigAgg/AggRenderer.cs b/MatterControlLib/Utilities/MarkdigAgg/AggRenderer.cs index 0a040be0d..caf808f10 100644 --- a/MatterControlLib/Utilities/MarkdigAgg/AggRenderer.cs +++ b/MatterControlLib/Utilities/MarkdigAgg/AggRenderer.cs @@ -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()); } diff --git a/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs b/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs new file mode 100644 index 000000000..347c59f81 --- /dev/null +++ b/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs @@ -0,0 +1,117 @@ +// 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 + { + 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 : + + renderer.Push(aggTable); + + foreach (var rowObj in table) + { + var row = (TableRow)rowObj; + + GuiWidget aggRow = row.IsHeader ? new TableHeadingRow() : new FlowLayoutWidget() + { + HAnchor = HAnchor.Fit, + VAnchor = VAnchor.Absolute, + Height = 25, + }; + + renderer.Push(aggRow); + + if (row.IsHeader) + { + // Update to desired header row styling + 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, + }; + + // 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: implement alignment into Agg types that won't throw when set + var alignment = table.ColumnDefinitions[columnIndex].Alignment; + if (alignment.HasValue) + { + switch (alignment) + { + //case TableColumnAlign.Center: + // aggCell.HAnchor |= HAnchor.Center; + // break; + //case TableColumnAlign.Right: + // aggCell.HAnchor |= HAnchor.Right; + // break; + //case TableColumnAlign.Left: + // aggCell.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(); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs b/MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs new file mode 100644 index 000000000..05b7cb948 --- /dev/null +++ b/MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs @@ -0,0 +1,42 @@ +// 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 TableHeadingRow: FlowLayoutWidget + { + public TableHeadingRow() + { + this.VAnchor = VAnchor.Fit; + this.HAnchor = HAnchor.Stretch; + this.Margin = new BorderDouble(3, 4, 0, 12); + // Likely needs to be implemented here as well + //this.RowPadding = new BorderDouble(0, 3); + } + + public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1) + { + if (childToAdd is TextWidget textWidget) + { + // textWidget.TextColor = new Color("#036ac3"); + textWidget.Bold = true; + } + else if (childToAdd is TextLinkX textLink) + { + foreach (var childTextWidget in childToAdd.Children.OfType()) + { + childTextWidget.Bold = true; + } + } + + return base.AddChild(childToAdd, indexInChildrenList); + } + } +} diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index c4f8114e2..3be867c69 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit c4f8114e2006faa32e6792f1a4d007ab2bbaed9a +Subproject commit 3be867c69f3fedc3dbee0874466743e75bc2062d From 11a778423008b36471aba4bfae8babfca04e628d Mon Sep 17 00:00:00 2001 From: John Lewin Date: Mon, 29 Aug 2022 08:20:32 -0700 Subject: [PATCH 2/2] Use shared type for TableRow behavior, set styles for alignment --- .../Utilities/MarkdigAgg/AggTableRenderer.cs | 41 +++++++++++-------- .../{TableHeadingRow.cs => AggTableRow.cs} | 24 +++++++---- 2 files changed, 42 insertions(+), 23 deletions(-) rename MatterControlLib/Utilities/MarkdigAgg/{TableHeadingRow.cs => AggTableRow.cs} (63%) diff --git a/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs b/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs index 347c59f81..58810d34b 100644 --- a/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs +++ b/MatterControlLib/Utilities/MarkdigAgg/AggTableRenderer.cs @@ -36,18 +36,16 @@ namespace Markdig.Renderers.Agg { var row = (TableRow)rowObj; - GuiWidget aggRow = row.IsHeader ? new TableHeadingRow() : new FlowLayoutWidget() + var aggRow = new AggTableRow() { - HAnchor = HAnchor.Fit, - VAnchor = VAnchor.Absolute, - Height = 25, + IsHeadingRow = row.IsHeader, }; renderer.Push(aggRow); if (row.IsHeader) { - // Update to desired header row styling + // Update to desired header row styling and/or moving into AggTableRow for consistency aggRow.BackgroundColor = MatterHackers.MatterControl.AppContext.Theme.TabBarBackground; } @@ -63,6 +61,16 @@ namespace Markdig.Renderers.Agg 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() { @@ -80,21 +88,22 @@ namespace Markdig.Renderers.Agg : cell.ColumnIndex; columnIndex = columnIndex >= table.ColumnDefinitions.Count ? table.ColumnDefinitions.Count - 1 : columnIndex; - // TODO: implement alignment into Agg types that won't throw when set - var alignment = table.ColumnDefinitions[columnIndex].Alignment; + // 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: - // aggCell.HAnchor |= HAnchor.Center; - // break; - //case TableColumnAlign.Right: - // aggCell.HAnchor |= HAnchor.Right; - // break; - //case TableColumnAlign.Left: - // aggCell.HAnchor |= HAnchor.Left; - // break; + case TableColumnAlign.Center: + aggCellFlow.HAnchor |= HAnchor.Center; + break; + case TableColumnAlign.Right: + aggCellFlow.HAnchor |= HAnchor.Right; + break; + case TableColumnAlign.Left: + aggCellFlow.HAnchor |= HAnchor.Left; + break; } } } diff --git a/MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs b/MatterControlLib/Utilities/MarkdigAgg/AggTableRow.cs similarity index 63% rename from MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs rename to MatterControlLib/Utilities/MarkdigAgg/AggTableRow.cs index 05b7cb948..1258993bf 100644 --- a/MatterControlLib/Utilities/MarkdigAgg/TableHeadingRow.cs +++ b/MatterControlLib/Utilities/MarkdigAgg/AggTableRow.cs @@ -10,29 +10,39 @@ using MatterHackers.Agg.UI; namespace Markdig.Renderers.Agg { - public class TableHeadingRow: FlowLayoutWidget + public class AggTableRow: FlowLayoutWidget { - public TableHeadingRow() + public AggTableRow() { this.VAnchor = VAnchor.Fit; - this.HAnchor = HAnchor.Stretch; this.Margin = new BorderDouble(3, 4, 0, 12); - // Likely needs to be implemented here as well - //this.RowPadding = new BorderDouble(0, 3); + + // 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"); - textWidget.Bold = true; + if (this.IsHeadingRow) + { + textWidget.Bold = true; + } } else if (childToAdd is TextLinkX textLink) { foreach (var childTextWidget in childToAdd.Children.OfType()) { - childTextWidget.Bold = true; + if (this.IsHeadingRow) + { + childTextWidget.Bold = true; + } } }