Merge pull request #5388 from larsbrubaker/main

main
This commit is contained in:
Lars Brubaker 2022-10-10 17:11:23 -07:00 committed by GitHub
commit db7722d4aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 56 additions and 3384 deletions

View file

@ -40,15 +40,17 @@ using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
public partial class InspectForm : WinformsSystemWindow.FormInspector
using WinTreeNode = System.Windows.Forms.TreeNode;
public partial class InspectForm : WinformsSystemWindow.FormInspector
{
private TreeNode activeTreeNode;
private WinTreeNode activeTreeNode;
private GuiWidget inspectedSystemWindow;
private Vector2 mousePosition;
private Dictionary<GuiWidget, TreeNode> aggTreeNodes = new Dictionary<GuiWidget, TreeNode>();
private Dictionary<IObject3D, TreeNode> sceneTreeNodes = new Dictionary<IObject3D, TreeNode>();
private Dictionary<GuiWidget, WinTreeNode> aggTreeNodes = new Dictionary<GuiWidget, WinTreeNode>();
private Dictionary<IObject3D, WinTreeNode> sceneTreeNodes = new Dictionary<IObject3D, WinTreeNode>();
private InteractiveScene scene;
private View3DWidget view3DWidget;
@ -145,7 +147,7 @@ namespace MatterHackers.MatterControl
activeTreeNode.Checked = false;
}
if (aggTreeNodes.TryGetValue(_inspectedWidget, out TreeNode treeNode))
if (aggTreeNodes.TryGetValue(_inspectedWidget, out WinTreeNode treeNode))
{
aggTreeView.SelectedNode = treeNode;
@ -182,14 +184,14 @@ namespace MatterHackers.MatterControl
}
}
private void AddItemEnsureAncestors(GuiWidget widget, string text = null, TreeNode childNode = null, bool showAllParents = true)
private void AddItemEnsureAncestors(GuiWidget widget, string text = null, WinTreeNode childNode = null, bool showAllParents = true)
{
if (text == null)
{
text = BuildDefaultName(widget);
}
if (aggTreeNodes.TryGetValue(widget, out TreeNode existingNode))
if (aggTreeNodes.TryGetValue(widget, out WinTreeNode existingNode))
{
if (childNode != null)
{
@ -199,7 +201,7 @@ namespace MatterHackers.MatterControl
}
else
{
var node = new TreeNode(text)
var node = new WinTreeNode(text)
{
Tag = widget
};
@ -230,9 +232,9 @@ namespace MatterHackers.MatterControl
}
}
private TreeNode AddItem(GuiWidget widget, TreeNode parentNode)
private WinTreeNode AddItem(GuiWidget widget, WinTreeNode parentNode)
{
var node = new TreeNode(BuildDefaultName(widget))
var node = new WinTreeNode(BuildDefaultName(widget))
{
Tag = widget
};
@ -252,9 +254,9 @@ namespace MatterHackers.MatterControl
return node;
}
private TreeNode AddItem(IObject3D item, TreeNode parentNode)
private WinTreeNode AddItem(IObject3D item, WinTreeNode parentNode)
{
var node = new TreeNode(BuildDefaultName(item))
var node = new WinTreeNode(BuildDefaultName(item))
{
Tag = item
};
@ -275,7 +277,7 @@ namespace MatterHackers.MatterControl
return node;
}
private void AddTree(GuiWidget widget, TreeNode parent)
private void AddTree(GuiWidget widget, WinTreeNode parent)
{
var node = AddItem(widget, parent);
@ -285,7 +287,7 @@ namespace MatterHackers.MatterControl
}
}
private void AddTree(IObject3D item, TreeNode parent)
private void AddTree(IObject3D item, WinTreeNode parent)
{
var node = AddItem(item, parent);
@ -348,7 +350,7 @@ namespace MatterHackers.MatterControl
public void MoveUpTree()
{
if (activeTreeNode?.Parent is TreeNode parent)
if (activeTreeNode?.Parent is WinTreeNode parent)
{
this.InspectedWidget = parent.Tag as GuiWidget;
}
@ -356,7 +358,7 @@ namespace MatterHackers.MatterControl
public void MoveDownTree()
{
if (activeTreeNode?.Nodes.Cast<TreeNode>().FirstOrDefault() is TreeNode firstChild)
if (activeTreeNode?.Nodes.Cast<WinTreeNode>().FirstOrDefault() is WinTreeNode firstChild)
{
this.InspectedWidget = firstChild.Tag as GuiWidget;
}
@ -502,11 +504,11 @@ namespace MatterHackers.MatterControl
private void InspectForm_Load(object sender, EventArgs e1)
{
var rootNode = new TreeNode("Theme");
var rootNode = new WinTreeNode("Theme");
var themeNode = new TreeNode("Theme");
var themeNode = new WinTreeNode("Theme");
var menuThemeNode = new TreeNode("MenuTheme");
var menuThemeNode = new WinTreeNode("MenuTheme");
rootNode.Nodes.Add(themeNode);
rootNode.Nodes.Add(menuThemeNode);

View file

@ -93,7 +93,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper">
<Version>28.0.1</Version>
<Version>29.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />

View file

@ -45,6 +45,8 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using global::MatterControl.Printing;
using Markdig.Agg;
using Markdig.Syntax.Inlines;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Image;
@ -588,9 +590,14 @@ namespace MatterHackers.MatterControl
{
try
{
Process.Start(input);
}
catch
var p = new Process();
p.StartInfo = new ProcessStartInfo(input)
{
UseShellExecute = true
};
p.Start();
}
catch
{
// hack because of this: https://github.com/dotnet/corefx/issues/10361
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@ -1132,7 +1139,12 @@ namespace MatterHackers.MatterControl
{
Workspaces = new ObservableCollection<PartWorkspace>();
Workspaces.CollectionChanged += (s, e) =>
// get markdown working correctly
MarkdownWidget.LaunchBrowser = ApplicationController.LaunchBrowser;
MarkdownWidget.RetrieveText = WebCache.RetrieveText;
MarkdownWidget.RetrieveImageSquenceAsync = WebCache.RetrieveImageSquenceAsync;
Workspaces.CollectionChanged += (s, e) =>
{
if (!restoringWorkspaces)
{

View file

@ -27,56 +27,8 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using global::MatterControl.Printing;
using Markdig.Agg;
using Markdig.Renderers.Agg;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.VertexSource;
using MatterHackers.DataConverters3D;
using MatterHackers.DataConverters3D.UndoCommands;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.DesignTools;
using MatterHackers.MatterControl.DesignTools.Operations;
using MatterHackers.MatterControl.Extensibility;
using MatterHackers.MatterControl.Library;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MatterControl.PartPreviewWindow.View3D;
using MatterHackers.MatterControl.Plugins;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrinterControls.PrinterConnections;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.SettingsManagement;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.MatterControl.Tour;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.VectorMath;
using MatterHackers.VectorMath.TrackBall;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MatterControl.Tests")]
[assembly: InternalsVisibleTo("MatterControl.AutomationTests")]
@ -84,11 +36,9 @@ using Newtonsoft.Json.Linq;
namespace MatterHackers.MatterControl
{
public class DragDropData
{
public View3DWidget View3DWidget { get; set; }
public ISceneContext SceneContext { get; set; }
}
}
public class DragDropData
{
public ISceneContext SceneContext { get; set; }
public View3DWidget View3DWidget { get; set; }
}
}

View file

@ -27,8 +27,8 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.MatterControl;
using System;
namespace Markdig.Agg
{

View file

@ -1,181 +0,0 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Transform;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.VertexSource;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
public class SvgWidget : GuiWidget
{
List<ColoredVertexSource> items = new List<ColoredVertexSource>();
private static XNamespace svg = "http://www.w3.org/2000/svg";
private ImageBuffer imageBuffer;
public double Scale { get; set; } = 0.7;
public SvgWidget(string filePath, double scale, int width = -1, int height = -1)
: this (File.OpenRead(filePath), scale, width, height)
{
}
public SvgWidget(Stream stream, double scale, int width = -1, int height = -1)
{
var root = XElement.Load(stream);
this.Scale = scale;
string viewBox = (string)root.Attribute("viewBox");
if (!string.IsNullOrEmpty(viewBox))
{
var segments = viewBox.Split(' ');
if (width == -1)
{
int.TryParse(segments[2], out width);
}
if (height == -1)
{
int.TryParse(segments[3], out height);
}
}
foreach (var elem in root.Elements(svg + "g"))
{
ProcTree(elem);
}
width = (int)(width * this.Scale);
height = (int)(height * this.Scale);
imageBuffer = new ImageBuffer(width, height);
this.MinimumSize = new Vector2(width, height);
var graphics2D = imageBuffer.NewGraphics2D();
graphics2D.SetTransform(Affine.NewScaling(this.Scale));
foreach (var item in items)
{
graphics2D.Render(item.VertexSource, item.Color);
}
imageBuffer.FlipY();
stream.Dispose();
//this.source = new PathStorage(svgDString);
}
private void ProcTree(XElement g)
{
foreach (var elem in g.Elements())
{
switch (elem.Name.LocalName)
{
case "path":
case "polygon":
string htmlColor = ((string)elem.Attribute("style"))?.Replace("fill:", "").Replace(";", "") ?? "#999";
if (elem.Name.LocalName == "polygon")
{
var path = new VertexStorage();
string pointsLine = ((string)elem.Attribute("points"))?.Trim();
var segments = pointsLine.Split(' ');
bool firstMove = true;
foreach(var segment in segments)
{
var point = segment.Split(',');
if (firstMove)
{
path.MoveTo(new Vector2(double.Parse(point[0]), double.Parse(point[1])));
firstMove = false;
}
else
{
path.LineTo(new Vector2(double.Parse(point[0]), double.Parse(point[1])));
}
}
path.ClosePolygon();
items.Add(new ColoredVertexSource()
{
VertexSource = path,
Color = new Color(htmlColor)
});
}
else
{
string dString = (string)elem.Attribute("d");
items.Add(new ColoredVertexSource()
{
VertexSource = new VertexStorage(dString),
Color = new Color(htmlColor)
});
}
break;
case "g":
ProcTree(elem);
break;
}
}
}
public override void OnDraw(Graphics2D graphics2D)
{
graphics2D.Render(imageBuffer, Point2D.Zero);
base.OnDraw(graphics2D);
}
public class ColoredVertexSource
{
public IVertexSource VertexSource { get; set; }
public Color Color { get; set; }
}
}
}

View file

@ -1,612 +0,0 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.ImageProcessing;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.CustomWidgets
{
public class TreeNode : FlowLayoutWidget, ICheckbox
{
private readonly GuiWidget content;
private TreeView _treeView;
private ImageBuffer _image = null;
private readonly TextWidget textWidget;
private readonly TreeExpandWidget expandWidget;
private readonly ImageWidget imageWidget;
private bool isDirty;
public TreeNode(ThemeConfig theme, bool useIcon = true, TreeNode nodeParent = null)
: base(FlowDirection.TopToBottom)
{
this.HAnchor = HAnchor.Fit | HAnchor.Left;
this.VAnchor = VAnchor.Fit;
this.NodeParent = nodeParent;
this.TitleBar = new FlowLayoutWidget();
this.TitleBar.Click += (s, e) =>
{
if (TreeView != null)
{
TreeView.SelectedNode = this;
TreeView.NotifyItemClicked(TitleBar, e);
}
};
TreeNode hitNode = null;
this.TitleBar.MouseDown += (s, e) =>
{
if (TreeView != null && e.Button == MouseButtons.Left)
{
if (e.Clicks == 1)
{
hitNode = this;
}
else if (e.Clicks == 2)
{
// Nodes can move around in the tree between clicks.
// Make sure we're hitting the same node twice.
if (this != hitNode)
{
return;
}
TreeView.SelectedNode = this;
if (this.Nodes.Count > 0)
{
this.Expanded = !this.Expanded;
}
else
{
this.TreeView.NotifyItemDoubleClicked(TitleBar, e);
}
}
}
};
this.AddChild(this.TitleBar);
// add a check box
expandWidget = new TreeExpandWidget(theme)
{
Expandable = GetNodeCount(false) != 0,
VAnchor = VAnchor.Fit | VAnchor.Center,
Height = 16,
Width = 16
};
expandWidget.Click += (s, e) =>
{
this.Expanded = !this.Expanded;
expandWidget.Expanded = this.Expanded;
};
this.TitleBar.AddChild(expandWidget);
this.HighlightRegion = new FlowLayoutWidget()
{
VAnchor = VAnchor.Fit,
HAnchor = HAnchor.Fit,
Padding = useIcon ? new BorderDouble(2) : new BorderDouble(4, 2),
Selectable = false
};
this.TitleBar.AddChild(this.HighlightRegion);
// add a check box
if (useIcon)
{
_image = new ImageBuffer(16, 16);
this.HighlightRegion.AddChild(imageWidget = new ImageWidget(this.Image, listenForImageChanged: false)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(right: 4),
Selectable = false
});
}
this.HighlightRegion.AddChild(textWidget = new TextWidget(this.Text, pointSize: theme.DefaultFontSize, textColor: theme.TextColor)
{
Selectable = false,
AutoExpandBoundsToText = true,
VAnchor = VAnchor.Center
});
content = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Fit | HAnchor.Left,
Visible = false, // content starts out not visible
Name = "content",
Margin = new BorderDouble(12, 3),
};
this.AddChild(content);
// Register listeners
this.Nodes.CollectionChanged += this.Nodes_CollectionChanged;
}
public override void OnKeyDown(KeyEventArgs keyEvent)
{
base.OnKeyDown(keyEvent);
var restoreFocus = Focused;
if (!keyEvent.Handled)
{
switch (keyEvent.KeyCode)
{
case Keys.Right:
this.Expanded = true;
keyEvent.Handled = true;
break;
case Keys.Left:
if (!this.Expanded)
{
if (this.NodeParent != null)
{
// navigate back up to the parent of this node
TreeView.SelectedNode = this.NodeParent;
TreeView.NotifyItemClicked(TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
restoreFocus = false;
}
else
{
this.Expanded = false;
}
keyEvent.Handled = true;
break;
}
}
if (restoreFocus && !Focused)
{
Focus();
}
}
private void Nodes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
// Assign NodeParent when items are added
foreach (var item in e.NewItems)
{
if (item is TreeNode treeNode)
{
treeNode.NodeParent = this;
}
}
}
isDirty = true;
}
public FlowLayoutWidget TitleBar { get; }
public FlowLayoutWidget HighlightRegion { get; }
// **** Not implemented ****
public void BeginEdit() => throw new NotImplementedException();
public void Collapse(bool collapseChildren) => throw new NotImplementedException();
public void Collapse() => throw new NotImplementedException();
public void EndEdit(bool cancel) => throw new NotImplementedException();
public void EnsureVisible() => throw new NotImplementedException();
public void ExpandAll() => throw new NotImplementedException();
public void Remove() => throw new NotImplementedException();
public int GetNodeCount(bool includeSubTrees)
{
if (includeSubTrees)
{
return this.Descendants<TreeNode>().Count();
}
return content?.Children.Where((c) => c is TreeNode).Count() ?? 0;
}
public bool AlwaysExpandable
{
get => expandWidget.AlwaysExpandable;
set => expandWidget.AlwaysExpandable = value;
}
public override void OnDraw(Graphics2D graphics2D)
{
if (isDirty)
{
// doing this during draw will often result in a enumeration changed
RebuildContentSection();
}
base.OnDraw(graphics2D);
}
public override void OnTextChanged(EventArgs e)
{
if (textWidget != null)
{
textWidget.Text = this.Text;
}
base.OnTextChanged(e);
}
public override void OnClosed(EventArgs e)
{
// Unregister listeners
this.Nodes.CollectionChanged -= this.Nodes_CollectionChanged;
base.OnClosed(e);
}
public void Toggle()
{
content.Visible = !content.Visible;
}
public IEnumerable<TreeNode> Ancestors()
{
var context = this.NodeParent;
while (context != null)
{
yield return context;
context = context.NodeParent;
}
}
private void RebuildContentSection()
{
// Remove but don't close all the current nodes
content.RemoveChildren();
using (content.LayoutLock())
{
// Then add them back in (after the change)
foreach (var node in Nodes)
{
node.NodeParent = this;
node.ClearRemovedFlag();
content.AddChild(node);
}
}
content.PerformLayout();
// If the node count is ending at 0 we removed content and need to rebuild the title bar so it will net have a + in it
expandWidget.Expandable = GetNodeCount(false) != 0;
isDirty = false;
}
public override string ToString()
{
return textWidget?.Text ?? "";
}
public bool Checked { get; set; }
public bool Editing { get; }
public bool Expandable
{
get => expandWidget.Expandable;
set => expandWidget.Expandable = value;
}
public bool ReserveIconSpace
{
get => expandWidget.ReserveIconSpace;
set => expandWidget.ReserveIconSpace = value;
}
private bool _expanded;
public bool Expanded
{
get => _expanded;
set
{
if (_expanded != value || content.Visible != value)
{
_expanded = value;
expandWidget.Expanded = _expanded;
content.Visible = _expanded && this.Nodes.Count > 0;
ExpandedChanged?.Invoke(this, null);
}
}
}
public TreeNode FirstNode { get; }
public ImageBuffer Image
{
get
{
return _image;
}
set
{
if (_image != value)
{
_image = value;
if (imageWidget != null)
{
imageWidget.Image = _image;
}
OnImageChanged(null);
}
}
}
public TreeNode LastNode { get; }
/// <summary>
/// Gets the zero-based depth of the tree node in the TreeView control.
/// </summary>
public int Level { get; }
// Summary:
// Gets the next sibling tree node.
//
// Returns:
// A TreeNode that represents the next sibling tree node.
public TreeNode NextNode { get; }
// Summary:
// Gets the next visible tree node.
//
// Returns:
// A TreeNode that represents the next visible tree node.
public TreeNode NextVisibleNode { get; }
// Summary:
// Gets or sets the font that is used to display the text on the tree node label.
//
// Returns:
// The StyledTypeFace that is used to display the text on the tree node label.
public StyledTypeFace NodeFont { get; set; }
// Summary:
// Gets the parent tree node of the current tree node.
//
// Returns:
// A TreeNode that represents the parent of the current tree
// node.
public TreeNode NodeParent { get; protected set; }
public ObservableCollection<TreeNode> Nodes { get; } = new ObservableCollection<TreeNode>();
public int PointSize { get; set; }
// Summary:
// Gets the previous sibling tree node.
//
// Returns:
// A TreeNode that represents the previous sibling tree node.
public TreeNode PrevNode { get; }
// Summary:
// Gets the previous visible tree node.
//
// Returns:
// A TreeNode that represents the previous visible tree node.
public TreeNode PrevVisibleNode { get; }
// Summary:
// Gets a value indicating whether the tree node is in the selected state.
//
// Returns:
// true if the tree node is in the selected state; otherwise, false.
public bool Selected
{
get
{
if (TreeView != null)
{
return TreeView.SelectedNode == this;
}
return false;
}
}
// Summary:
// Gets or sets the image list index value of the image that is displayed when the
// tree node is in the selected state.
//
// Returns:
// A zero-based index value that represents the image position in an ImageList.
public ImageBuffer SelectedImage { get; set; }
// Summary:
// Gets or sets the index of the image that is used to indicate the state of the
// TreeNode when the parent TreeView has
// its TreeView.CheckBoxes property set to false.
//
// Returns:
// The index of the image that is used to indicate the state of the TreeNode.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The specified index is less than -1 or greater than 14.
public ImageBuffer StateImage { get; set; }
// Summary:
// Gets or sets the object that contains data about the tree node.
//
// Returns:
// An System.Object that contains data about the tree node. The default is null.
public object Tag { get; set; }
public Color TextColor { get; set; }
// Summary:
// Gets the parent tree view that the tree node is assigned to.
//
// Returns:
// A TreeView that represents the parent tree view that the
// tree node is assigned to, or null if the node has not been assigned to a tree
// view.
public virtual TreeView TreeView
{
get => _treeView ?? NodeParent.TreeView;
set => _treeView = value;
}
private void OnImageChanged(EventArgs args)
{
ImageChanged?.Invoke(this, null);
}
public event EventHandler CheckedStateChanged;
public event EventHandler ExpandedChanged;
public event EventHandler ImageChanged;
private class TreeExpandWidget : FlowLayoutWidget
{
private readonly ImageBuffer arrowRight;
private readonly ImageBuffer arrowDown;
private readonly ImageBuffer placeholder;
private readonly ThemedIconButton imageButton = null;
public TreeExpandWidget(ThemeConfig theme)
{
arrowRight = StaticData.Instance.LoadIcon("fa-angle-right_12.png", 12, 12).SetToColor(theme.TextColor);
arrowDown = StaticData.Instance.LoadIcon("fa-angle-down_12.png", 12, 12).SetToColor(theme.TextColor);
placeholder = new ImageBuffer(16, 16);
this.Margin = new BorderDouble(right: 4);
imageButton = new ThemedIconButton(placeholder, theme)
{
MinimumSize = new Vector2(16 * DeviceScale, 16 * DeviceScale),
VAnchor = VAnchor.Center,
Selectable = false,
Width = 16 * DeviceScale,
Height = 16 * DeviceScale
};
this.AddChild(imageButton);
}
private bool _alwaysExpandable;
public bool AlwaysExpandable
{
get => _alwaysExpandable;
set
{
imageButton.SetIcon(_expanded ? arrowDown : arrowRight);
_alwaysExpandable = value;
}
}
private bool? _expandable = null;
public bool Expandable
{
get => _expandable == true || this.AlwaysExpandable;
set
{
if (_expandable != value)
{
_expandable = value;
}
this.EnsureExpansionState();
}
}
private bool _expanded;
public bool Expanded
{
get => _expanded;
set
{
if (_expanded != value)
{
_expanded = value;
this.EnsureExpansionState();
}
}
}
private void EnsureExpansionState()
{
if (!this.Expandable)
{
if (this.ReserveIconSpace)
{
imageButton.SetIcon(placeholder);
}
imageButton.Visible = this.ReserveIconSpace;
}
else
{
imageButton.Visible = true;
imageButton.SetIcon(_expanded ? arrowDown : arrowRight);
}
}
public bool ReserveIconSpace { get; set; } = true;
}
}
}

View file

@ -1,455 +0,0 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections;
using System.Linq;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.CustomWidgets
{
public class TreeView : ScrollableWidget
{
protected ThemeConfig theme;
public TreeView(ThemeConfig theme)
: this(0, 0, theme)
{
}
public TreeView(int width, int height, ThemeConfig theme)
: base(width, height)
{
this.theme = theme;
this.AutoScroll = true;
this.HAnchor = HAnchor.Stretch;
this.VAnchor = VAnchor.Stretch;
}
#region Events
public event EventHandler AfterCheck;
public event EventHandler AfterCollapse;
public event EventHandler AfterExpand;
public event EventHandler AfterLabelEdit;
public event EventHandler<TreeNode> AfterSelect;
public event EventHandler BeforeCheck;
internal void NotifyItemClicked(GuiWidget sourceWidget, MouseEventArgs e)
{
this.NodeMouseClick?.Invoke(sourceWidget, e);
}
internal void NotifyItemDoubleClicked(GuiWidget sourceWidget, MouseEventArgs e)
{
this.NodeMouseDoubleClick?.Invoke(sourceWidget, e);
}
public event EventHandler BeforeCollapse;
public event EventHandler BeforeExpand;
public event EventHandler BeforeLabelEdit;
public event EventHandler<TreeNode> BeforeSelect;
public event EventHandler NodeMouseClick;
public event EventHandler NodeMouseDoubleClick;
public event EventHandler NodeMouseHover;
#endregion Events
#region Properties
// Summary:
// Gets or sets a value indicating whether check boxes are displayed next to the
// tree nodes in the tree view control.
//
// Returns:
// true if a check box is displayed next to each tree node in the tree view control;
// otherwise, false. The default is false.
public bool CheckBoxes { get; set; }
// Summary:
// Gets or sets a value indicating whether the selection highlight spans the width
// of the tree view control.
//
// Returns:
// true if the selection highlight spans the width of the tree view control; otherwise,
// false. The default is false.
public bool FullRowSelect { get; set; }
// Summary:
// Gets or sets a value indicating whether the selected tree node remains highlighted
// even when the tree view has lost the focus.
//
// Returns:
// true if the selected tree node is not highlighted when the tree view has lost
// the focus; otherwise, false. The default is true.
public bool HideSelection { get; set; }
// Summary:
// Gets or sets the distance to indent each child tree node level.
//
// Returns:
// The distance, in pixels, to indent each child tree node level. The default value
// is 19.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The assigned value is less than 0 (see Remarks).-or- The assigned value is greater
// than 32,000.
public int Indent { get; set; }
// Summary:
// Gets or sets the height of each tree node in the tree view control.
//
// Returns:
// The height, in pixels, of each tree node in the tree view.
//
// Exceptions:
// T:System.ArgumentOutOfRangeException:
// The assigned value is less than one.-or- The assigned value is greater than the
// System.Int16.MaxValue value.
public int ItemHeight { get; set; }
// Summary:
// Gets or sets a value indicating whether the label text of the tree nodes can
// be edited.
//
// Returns:
// true if the label text of the tree nodes can be edited; otherwise, false. The
// default is false.
public bool LabelEdit { get; set; }
// Summary:
// Gets or sets the color of the lines connecting the nodes of the TreeView
// control.
//
// Returns:
// The System.Drawing.Color of the lines connecting the tree nodes.
public Color LineColor { get; set; }
// Summary:
// Gets or sets the delimiter string that the tree node path uses.
//
// Returns:
// The delimiter string that the tree node TreeNode.FullPath
// property uses. The default is the backslash character (\).
public string PathSeparator { get; set; }
public Color TextColor { get; set; } = Color.Black;
public double PointSize { get; set; } = 12;
// Summary:
// Gets or sets a value indicating whether the tree view control displays scroll
// bars when they are needed.
//
// Returns:
// true if the tree view control displays scroll bars when they are needed; otherwise,
// false. The default is true.
public bool Scrollable { get; set; }
// Summary:
// Gets or sets the tree node that is currently selected in the tree view control.
//
// Returns:
// The TreeNode that is currently selected in the tree view
// control.
private TreeNode _selectedNode;
public void Clear()
{
this.ScrollArea.CloseChildren();
// Release held reference
_selectedNode = null;
}
public override void OnKeyDown(KeyEventArgs keyEvent)
{
if (!keyEvent.Handled)
{
switch (keyEvent.KeyCode)
{
case Keys.Up:
var prev = PreviousVisibleTreeNode(SelectedNode);
if (prev != null)
{
SelectedNode = prev;
keyEvent.Handled = true;
prev.TreeView.NotifyItemClicked(prev.TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
break;
case Keys.Down:
var next = NextVisibleTreeNode(SelectedNode);
if (next != null)
{
SelectedNode = next;
keyEvent.Handled = true;
next.TreeView.NotifyItemClicked(next.TreeView, new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
}
break;
}
}
base.OnKeyDown(keyEvent);
}
private TreeNode NextVisibleTreeNode(TreeNode treeNode)
{
var nodes = this.Descendants<TreeNode>((child) => child.Visible).ToList();
var selectedIndex = nodes.IndexOf(SelectedNode);
if (selectedIndex < nodes.Count - 1)
{
return nodes[selectedIndex + 1];
}
return null;
}
private TreeNode PreviousVisibleTreeNode(TreeNode treeNode)
{
var nodes = this.Descendants<TreeNode>((child) => child.Visible).ToList();
var selectedIndex = nodes.IndexOf(SelectedNode);
if (selectedIndex > 0)
{
return nodes[selectedIndex - 1];
}
return null;
}
public TreeNode SelectedNode
{
get => _selectedNode;
set
{
if (value != _selectedNode)
{
OnBeforeSelect(null);
var hadFocus = false;
// if the current selection (before change) is !null than clear its background color
if (_selectedNode != null)
{
hadFocus = _selectedNode.ContainsFocus;
_selectedNode.HighlightRegion.BackgroundColor = Color.Transparent;
}
// change the selection
_selectedNode = value;
if (_selectedNode != null)
{
// Ensure tree is expanded, walk backwards to the root, reverse, expand back to this node
foreach (var ancestor in _selectedNode.Ancestors().Reverse())
{
ancestor.Expanded = true;
}
}
if (_selectedNode != null)
{
_selectedNode.HighlightRegion.BackgroundColor = theme.AccentMimimalOverlay;
}
this.ScrollIntoView(_selectedNode);
if (hadFocus)
{
_selectedNode?.Focus();
}
OnAfterSelect(null);
}
}
}
public bool ShowLines { get; set; }
public bool ShowNodeToolTips { get; set; }
public bool ShowPlusMinus { get; set; }
public bool ShowRootLines { get; set; }
public bool Sorted { get; set; }
public IComparer TreeViewNodeSorter { get; set; }
// Summary:
// Gets the number of tree nodes that can be fully visible in the tree view control.
//
// Returns:
// The number of TreeNode items that can be fully visible in
// the TreeView control.
public int VisibleCount { get; }
#endregion Properties
// Summary:
// Disables any redrawing of the tree view.
public void BeginUpdate()
{
throw new NotImplementedException();
}
// Summary:
// Collapses all the tree nodes.
public void CollapseAll()
{
throw new NotImplementedException();
}
// Summary:
// Enables the redrawing of the tree view.
public void EndUpdate()
{
throw new NotImplementedException();
}
// Summary:
// Expands all the tree nodes.
public void ExpandAll()
{
throw new NotImplementedException();
}
// Summary:
// Retrieves the tree node that is at the specified point.
//
// Parameters:
// pt:
// The System.Drawing.Point to evaluate and retrieve the node from.
//
// Returns:
// The TreeNode at the specified point, in tree view (client)
// coordinates, or null if there is no node at that location.
public TreeNode GetNodeAt(Vector2 pt)
{
throw new NotImplementedException();
}
/// <summary>
/// Retrieves the number of tree nodes, optionally including those in all subtrees,
/// assigned to the tree view control.
/// </summary>
/// <param name="includeSubTrees">true to count the TreeNode items that the subtrees contain;
/// otherwise, false.</param>
/// <returns>The number of tree nodes, optionally including those in all subtrees, assigned
/// to the tree view control.</returns>
public int GetNodeCount(bool includeSubTrees)
{
throw new NotImplementedException();
}
public void Sort()
{
throw new NotImplementedException();
}
protected internal virtual void OnAfterCollapse(EventArgs e)
{
throw new NotImplementedException();
}
protected internal virtual void OnBeforeCollapse(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterCheck(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterExpand(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterLabelEdit(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnAfterSelect(TreeNode e)
{
AfterSelect?.Invoke(this, e);
}
protected virtual void OnBeforeCheck(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeExpand(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeLabelEdit(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnBeforeSelect(TreeNode e)
{
BeforeSelect?.Invoke(this, e);
}
protected virtual void OnNodeMouseClick(EventArgs e)
{
throw new NotImplementedException();
}
protected virtual void OnNodeMouseDoubleClick(EventArgs e)
{
throw new NotImplementedException();
}
}
}

View file

@ -79,6 +79,7 @@
<ProjectReference Include="..\Submodules\agg-sharp\Gui\Gui.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\ImageProcessing\ImageProcessing.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\MarchingSquares\MarchingSquares.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\MarkdigAgg\MarkdigAgg.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\MeshThumbnails\MeshThumbnails\MeshThumbnails.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\VectorMath\VectorMath.csproj" />
<ProjectReference Include="..\Submodules\agg-sharp\Tesselate\Tesselate.csproj" />
@ -92,11 +93,11 @@
<ItemGroup>
<PackageReference Include="AngleSharp" Version="0.17.1" />
<PackageReference Include="CsvHelper" Version="28.0.1" />
<PackageReference Include="CsvHelper" Version="29.0.0" />
<PackageReference Include="Lucene.Net" Version="4.8.0-beta00005" />
<PackageReference Include="Lucene.Net.Analysis.Common" Version="4.8.0-beta00005" />
<PackageReference Include="Lucene.Net.QueryParser" Version="4.8.0-beta00005" />
<PackageReference Include="Markdig" Version="0.30.3" />
<PackageReference Include="Markdig" Version="0.30.4" />
<PackageReference Include="MathParser.org-mXparser" Version="5.0.7" />
<PackageReference Include="MIConvexHull" Version="1.1.19.1019" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />

View file

@ -47,7 +47,10 @@ namespace MatterHackers.MatterControl
private TypeFacePrinter typeFacePrinter = null;
private PrinterConfig printer = null;
private int forceStartLine = -1;
/// <summary>
/// The first line to show from the existing visible lines. If -1 then show to the bottom of the list.
/// </summary>
private int forceStartLine = -1;
private Func<TerminalLine, string> _lineFilterFunction;

View file

@ -285,7 +285,7 @@ namespace MatterHackers.MatterControl
if (!string.IsNullOrWhiteSpace(article.Path))
{
markdownWidget.LoadUri(new Uri(ApplicationController.Instance.HelpArticleSource, article.Path), sourceArticle: article);
markdownWidget.LoadUri(new Uri(ApplicationController.Instance.HelpArticleSource, article.Path));
}
else
{

View file

@ -28,6 +28,7 @@ either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.Library.Widgets;
using MatterHackers.MatterControl.SlicerConfiguration;

View file

@ -1,45 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
namespace Markdig.Renderers.Agg
{
public class CodeBlockX : FlowLeftRightWithWrapping
{
private ThemeConfig theme;
public CodeBlockX(ThemeConfig theme)
{
this.theme = theme;
this.HAnchor = HAnchor.Stretch;
this.VAnchor = VAnchor.Fit;
this.Margin = 12;
this.Padding = 6;
this.BackgroundColor = theme.MinimalShade;
}
}
public class AggCodeBlockRenderer : AggObjectRenderer<CodeBlock>
{
private ThemeConfig theme;
public AggCodeBlockRenderer(ThemeConfig theme)
{
this.theme = theme;
}
protected override void Write(AggRenderer renderer, CodeBlock obj)
{
//var paragraph = new Paragraph();
//paragraph.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.CodeBlockStyleKey);
renderer.Push(new CodeBlockX(theme));
renderer.WriteLeafRawLines(obj);
renderer.Pop();
}
}
}

View file

@ -1,36 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
namespace Markdig.Renderers.Agg
{
public class AggHeadingRenderer : AggObjectRenderer<HeadingBlock>
{
protected override void Write(AggRenderer renderer, HeadingBlock obj)
{
// var paragraph = new Paragraph();
// ComponentResourceKey styleKey = null;
// switch (obj.Level)
// {
// case 1: styleKey = Styles.Heading1StyleKey; break;
// case 2: styleKey = Styles.Heading2StyleKey; break;
// case 3: styleKey = Styles.Heading3StyleKey; break;
// case 4: styleKey = Styles.Heading4StyleKey; break;
// case 5: styleKey = Styles.Heading5StyleKey; break;
// case 6: styleKey = Styles.Heading6StyleKey; break;
// }
// if (styleKey != null)
// {
// paragraph.SetResourceReference(FrameworkContentElement.StyleProperty, styleKey);
// }
renderer.Push(new HeadingRowX()); // paragraph);
renderer.WriteLeafInline(obj);
renderer.Pop();
}
}
}

View file

@ -1,101 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.ImageProcessing;
using MatterHackers.MatterControl;
namespace Markdig.Renderers.Agg
{
public class ListX : FlowLayoutWidget
{
public ListX()
: base(FlowDirection.TopToBottom)
{
this.VAnchor = VAnchor.Fit;
this.HAnchor = HAnchor.Stretch;
}
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
if (childToAdd is TextWidget textWidget)
{
textWidget.TextColor = new Color("#036ac3");
textWidget.PointSize = 11;
}
return base.AddChild(childToAdd, indexInChildrenList);
}
}
public class ListItemX : FlowLayoutWidget
{
private FlowLayoutWidget content;
public ListItemX(ThemeConfig theme)
{
this.VAnchor = VAnchor.Fit;
this.HAnchor = HAnchor.Stretch;
base.AddChild(new ImageWidget(StaticData.Instance.LoadIcon("bullet.png", 16, 16).SetToColor(theme.TextColor))
{
Margin = new BorderDouble(top: 1, left: 10),
VAnchor = VAnchor.Top,
});
base.AddChild(content = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Stretch
});
}
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
// TODOD: Anything else required for list children?
return content.AddChild(childToAdd, indexInChildrenList);
}
}
public class AggListRenderer : AggObjectRenderer<ListBlock>
{
private ThemeConfig theme;
public AggListRenderer(ThemeConfig theme)
{
this.theme = theme;
}
protected override void Write(AggRenderer renderer, ListBlock listBlock)
{
//var list = new List();
//if (listBlock.IsOrdered)
//{
// list.MarkerStyle = TextMarkerStyle.Decimal;
// if (listBlock.OrderedStart != null && (listBlock.DefaultOrderedStart != listBlock.OrderedStart))
// {
// list.StartIndex = int.Parse(listBlock.OrderedStart);
// }
//}
//else
//{
// list.MarkerStyle = TextMarkerStyle.Disc;
//}
renderer.Push(new ListX()); // list);
foreach (var item in listBlock)
{
renderer.Push(new ListItemX(theme));
renderer.WriteChildren(item as ListItemBlock);
renderer.Pop();
}
renderer.Pop();
}
}
}

View file

@ -1,138 +0,0 @@
/*
Copyright(c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Net;
using Markdig.Renderers;
using Markdig.Renderers.Agg;
using MatterHackers.Agg.UI;
namespace Markdig.Agg
{
public class AggMarkdownDocument
{
private string _markDownText = null;
private MarkdownPipeline _pipeLine = null;
private static readonly MarkdownPipeline DefaultPipeline = new MarkdownPipelineBuilder().UseSupportedExtensions().Build();
public AggMarkdownDocument()
{
}
public AggMarkdownDocument(Uri baseUri)
{
this.BaseUri = baseUri;
}
public string MatchingText { get; set; }
public Uri BaseUri { get; set; } = new Uri("https://www.matterhackers.com/");
public List<MarkdownDocumentLink> Children { get; private set; } = new List<MarkdownDocumentLink>();
public static AggMarkdownDocument Load(Uri uri)
{
var webClient = new WebClient();
string rawText = webClient.DownloadString(uri);
return new AggMarkdownDocument(uri)
{
Markdown = rawText,
};
}
/// <summary>
/// Gets or sets the Markdown to display.
/// </summary>
public string Markdown
{
get => _markDownText;
set
{
if (_markDownText != value)
{
_markDownText = value;
}
}
}
/// <summary>
/// Gets or sets the Markdown pipeline to use.
/// </summary>
public MarkdownPipeline Pipeline
{
get => _pipeLine ?? DefaultPipeline;
set
{
if (_pipeLine != value)
{
_pipeLine = value;
}
}
}
public void Parse(GuiWidget guiWidget = null)
{
if (!string.IsNullOrEmpty(this.Markdown))
{
MarkdownPipeline pipeline;
if (!string.IsNullOrWhiteSpace(MatchingText))
{
var builder = new MarkdownPipelineBuilder().UseSupportedExtensions();
builder.InlineParsers.Add(new MatchingTextParser(MatchingText));
pipeline = builder.Build();
}
else
{
pipeline = Pipeline;
}
var rootWidget = guiWidget ?? new GuiWidget();
var renderer = new AggRenderer(rootWidget)
{
BaseUri = this.BaseUri,
ChildLinks = new List<MarkdownDocumentLink>()
};
pipeline.Setup(renderer);
var document = Markdig.Markdown.Parse(this.Markdown, pipeline);
renderer.Render(document);
this.Children = renderer.ChildLinks;
}
}
}
}

View file

@ -1,55 +0,0 @@
/*
Copyright(c) 2019, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using Markdig.Renderers.Agg.Inlines;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
namespace Markdig.Renderers.Agg
{
public class AggMatchingTextRenderer : AggObjectRenderer<MatchingTextInline>
{
private ThemeConfig theme;
public AggMatchingTextRenderer(ThemeConfig theme)
{
this.theme = theme;
}
protected override void Write(AggRenderer renderer, MatchingTextInline obj)
{
renderer.Push(new CodeInlineX(theme)
{
BackgroundColor = theme.AccentMimimalOverlay
});
renderer.WriteText(obj.MatchingText);
renderer.Pop();
}
}
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
namespace Markdig.Renderers.Agg
{
/// <summary>
/// A base class for Agg rendering <see cref="Block"/> and <see cref="Markdig.Syntax.Inlines.Inline"/> Markdown objects.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <seealso cref="Markdig.Renderers.IMarkdownObjectRenderer" />
public abstract class AggObjectRenderer<TObject> : MarkdownObjectRenderer<AggRenderer, TObject>
where TObject : MarkdownObject
{
}
}

View file

@ -1,61 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
public class AutoFit : GuiWidget
{
public AutoFit()
{
this.HAnchor = HAnchor.Fit | HAnchor.Left;
this.VAnchor = VAnchor.Fit;
}
}
public class ParagraphX : FlowLeftRightWithWrapping, IHardBreak
{
public ParagraphX(bool bottomMargin)
{
// Adding HAnchor and initial fixed width properties to resolve excess vertical whitespace added during collapse to width 0
//
// TODO: Revise impact to FlowLeftRightWithWrapping
this.HAnchor = HAnchor.Stretch;
this.Width = 5000;
if (bottomMargin)
{
Margin = new BorderDouble(0, 0, 0, 12);
}
}
}
//public class ParagraphRenderer :
public class AggParagraphRenderer : AggObjectRenderer<ParagraphBlock>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, ParagraphBlock obj)
{
var bottomMargin = false;
if (obj.Parent is MarkdownDocument document
&& obj.Parent.Count > 1
&& obj.Line != 0)
{
bottomMargin = true;
}
var paragraph = new ParagraphX(bottomMargin)
{
RowMargin = 0,
RowPadding = 3
};
renderer.Push(paragraph);
renderer.WriteLeafInline(obj);
renderer.Pop();
}
}
}

View file

@ -1,25 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
public class QuoteBlockX : AutoFit{ }
public class AggQuoteBlockRenderer : AggObjectRenderer<QuoteBlock>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, QuoteBlock obj)
{
// var section = new Section();
renderer.Push(new QuoteBlockX()); // section);
renderer.WriteChildren(obj);
//section.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.QuoteBlockStyleKey);
renderer.Pop();
}
}
}

View file

@ -1,253 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Markdig.Agg;
using Markdig.Helpers;
using Markdig.Renderers.Agg;
using Markdig.Renderers.Agg.Inlines;
using Markdig.Syntax;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
namespace Markdig.Renderers
{
public class TextWordX : TextWidget
{
public TextWordX(ThemeConfig theme)
: base("", pointSize: 10, textColor: theme.TextColor)
{
this.AutoExpandBoundsToText = true;
}
}
public class TextSpaceX : TextWidget, ISkipIfFirst
{
public TextSpaceX(ThemeConfig theme)
: base("", pointSize: 10, textColor: theme.TextColor)
{
this.AutoExpandBoundsToText = true;
}
}
public class LineBreakX : GuiWidget, IHardBreak
{
public LineBreakX()
{
}
}
/// <summary>
/// Agg renderer for a Markdown <see cref="AggMarkdownDocument"/> object.
/// </summary>
/// <seealso cref="RendererBase" />
public class AggRenderer : RendererBase
{
private readonly Stack<GuiWidget> stack = new Stack<GuiWidget>();
private char[] buffer;
private ThemeConfig theme;
public GuiWidget RootWidget { get; }
public Uri BaseUri { get; set; } = new Uri("https://www.matterhackers.com/");
public List<MarkdownDocumentLink> ChildLinks { get; internal set; }
public AggRenderer(ThemeConfig theme)
{
this.theme = theme;
}
public AggRenderer(GuiWidget rootWidget)
{
this.theme = ApplicationController.Instance.Theme;
buffer = new char[1024];
RootWidget = rootWidget;
stack.Push(rootWidget);
// Default block renderers
ObjectRenderers.Add(new AggCodeBlockRenderer(theme));
ObjectRenderers.Add(new AggListRenderer(theme));
ObjectRenderers.Add(new AggHeadingRenderer());
ObjectRenderers.Add(new AggParagraphRenderer());
ObjectRenderers.Add(new AggQuoteBlockRenderer());
ObjectRenderers.Add(new AggThematicBreakRenderer());
// Default inline renderers
ObjectRenderers.Add(new AggAutolinkInlineRenderer());
ObjectRenderers.Add(new AggCodeInlineRenderer(theme));
ObjectRenderers.Add(new AggDelimiterInlineRenderer());
ObjectRenderers.Add(new AggEmphasisInlineRenderer());
ObjectRenderers.Add(new AggLineBreakInlineRenderer());
ObjectRenderers.Add(new AggLinkInlineRenderer());
ObjectRenderers.Add(new AggLiteralInlineRenderer());
ObjectRenderers.Add(new AggMatchingTextRenderer(theme));
// Extension renderers
ObjectRenderers.Add(new AggTableRenderer());
//ObjectRenderers.Add(new AggTaskListRenderer());
}
/// <inheritdoc/>
public override object Render(MarkdownObject markdownObject)
{
Write(markdownObject);
UiThread.RunOnIdle(() =>
{
// TODO: investigate why this is required, layout should have already done this
// but it didn't. markdown that looks like the following will not layout correctly without this
// string badLayoutMarkdown = "I [s]()\n\nT";
if (RootWidget?.Parent?.Parent != null)
{
RootWidget.Parent.Parent.Width = RootWidget.Parent.Parent.Width - 1;
}
});
return RootWidget;
}
/// <summary>
/// Writes the inlines of a leaf inline.
/// </summary>
/// <param name="leafBlock">The leaf block.</param>
/// <returns>This instance</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteLeafInline(LeafBlock leafBlock)
{
if (leafBlock == null) throw new ArgumentNullException(nameof(leafBlock));
var inline = (Syntax.Inlines.Inline)leafBlock.Inline;
while (inline != null)
{
Write(inline);
inline = inline.NextSibling;
}
}
/// <summary>
/// Writes the lines of a <see cref="LeafBlock"/>
/// </summary>
/// <param name="leafBlock">The leaf block.</param>
public void WriteLeafRawLines(LeafBlock leafBlock)
{
if (leafBlock == null) throw new ArgumentNullException(nameof(leafBlock));
if (leafBlock.Lines.Lines != null)
{
var lines = leafBlock.Lines;
var slices = lines.Lines;
for (var i = 0; i < lines.Count; i++)
{
if (i != 0)
//if (stack.Peek() is FlowLayoutWidget)
//{
// this.Pop();
// this.Push(new ParagraphX());
//}
WriteInline(new LineBreakX()); // new LineBreak());
WriteText(ref slices[i].Slice);
}
}
}
internal void Push(GuiWidget o)
{
stack.Push(o);
}
internal void Pop()
{
var popped = stack.Pop();
if (stack.Count > 0)
{
var top = stack.Peek();
top.AddChild(popped);
}
}
internal void WriteBlock(GuiWidget block)
{
stack.Peek().AddChild(block);
}
internal void WriteInline(GuiWidget inline)
{
AddInline(stack.Peek(), inline);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void WriteText(ref StringSlice slice)
{
if (slice.Start > slice.End)
{
return;
}
WriteText(slice.Text, slice.Start, slice.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void WriteText(string text)
{
var words = text.Split(' ');
bool first = true;
foreach (var word in words)
{
if (!first)
{
WriteInline(new TextSpaceX(theme)
{
Text = " "
});
}
if (word.Length > 0)
{
WriteInline(new TextWordX(theme)
{
Text = word
});
}
first = false;
}
}
internal void WriteText(string text, int offset, int length)
{
if (text == null)
{
return;
}
if (offset == 0 && text.Length == length)
{
WriteText(text);
}
else
{
if (length > buffer.Length)
{
buffer = text.ToCharArray();
WriteText(new string(buffer, offset, length));
}
else
{
text.CopyTo(offset, buffer, 0, length);
WriteText(new string(buffer, 0, length));
}
}
}
private static void AddInline(GuiWidget parent, GuiWidget inline)
{
parent.AddChild(inline);
}
}
}

View file

@ -1,26 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax;
namespace Markdig.Renderers.Agg
{
public class ThematicBreakX : AutoFit{ }
public class AggThematicBreakRenderer : AggObjectRenderer<ThematicBreakBlock>
{
protected override void Write(AggRenderer renderer, ThematicBreakBlock obj)
{
//var line = new System.Windows.Shapes.Line { X2 = 1 };
//line.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.ThematicBreakStyleKey);
//var paragraph = new Paragraph
//{
// Inlines = { new InlineUIContainer(line) }
//};
renderer.WriteBlock(new ThematicBreakX()); // paragraph);
}
}
}

View file

@ -1,43 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Renderers.Agg.Inlines;
using Markdig.Syntax;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
public class HeadingRowX : FlowLeftRightWithWrapping
{
public HeadingRowX()
{
this.VAnchor = VAnchor.Fit;
this.HAnchor = HAnchor.Stretch;
this.Margin = new BorderDouble(3, 4, 0, 12);
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.PointSize = 14;
}
else if (childToAdd is TextLinkX textLink)
{
foreach (var child in childToAdd.Children)
{
if (child is TextWidget childTextWidget)
{
childTextWidget.PointSize = 14;
}
}
}
return base.AddChild(childToAdd, indexInChildrenList);
}
}
}

View file

@ -1,39 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System;
using Markdig.Syntax.Inlines;
namespace Markdig.Renderers.Agg.Inlines
{
public class AutoLinkInlineX : AutoFit{ }
/// <summary>
/// A Agg renderer for a <see cref="AutolinkInline"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Agg.AggObjectRenderer{Markdig.Syntax.Inlines.AutolinkInline}" />
public class AggAutolinkInlineRenderer : AggObjectRenderer<AutolinkInline>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, AutolinkInline link)
{
var url = link.Url;
if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
{
url = "#";
}
//var hyperlink = new Hyperlink
//{
// Command = Commands.Hyperlink,
// CommandParameter = url,
// NavigateUri = new Uri(url, UriKind.RelativeOrAbsolute),
// ToolTip = url,
//};
renderer.WriteInline(new AutoLinkInlineX());
}
}
}

View file

@ -1,50 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax.Inlines;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
namespace Markdig.Renderers.Agg.Inlines
{
public class CodeInlineX : FlowLayoutWidget
{
private ThemeConfig theme;
public CodeInlineX(ThemeConfig theme)
{
this.theme = theme;
this.HAnchor = HAnchor.Fit;
this.VAnchor = VAnchor.Fit;
this.Padding = 4;
this.BackgroundColor = theme.MinimalShade;
}
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
return base.AddChild(childToAdd, indexInChildrenList);
}
}
public class AggCodeInlineRenderer : AggObjectRenderer<CodeInline>
{
private ThemeConfig theme;
public AggCodeInlineRenderer(ThemeConfig theme)
{
this.theme = theme;
}
protected override void Write(AggRenderer renderer, CodeInline obj)
{
//var run = new Run(obj.Content);
//run.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.CodeStyleKey);
//renderer.WriteInline(new CodeInlineX());
renderer.Push(new CodeInlineX(theme));
renderer.WriteText(obj.Content);
renderer.Pop();
}
}
}

View file

@ -1,24 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax.Inlines;
namespace Markdig.Renderers.Agg.Inlines
{
public class DelimiterInlineX : AutoFit{ }
/// <summary>
/// A Agg renderer for a <see cref="DelimiterInline"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Agg.AggObjectRenderer{Markdig.Syntax.Inlines.DelimiterInline}" />
public class AggDelimiterInlineRenderer : AggObjectRenderer<DelimiterInline>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, DelimiterInline obj)
{
renderer.WriteText(obj.ToLiteral());
renderer.WriteChildren(obj);
}
}
}

View file

@ -1,94 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax.Inlines;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg.Inlines
{
public class EmphasisInlineX : FlowLayoutWidget, IWrapChildrenSeparatly
{
private char delimiter;
public EmphasisInlineX(char delimiter)
{
this.HAnchor = HAnchor.Fit;
this.VAnchor = VAnchor.Fit;
this.delimiter = delimiter;
}
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
if (childToAdd is TextWidget textWidget)
{
switch (delimiter)
{
case '~':
textWidget.StrikeThrough = true;
break;
case '*':
default:
textWidget.Bold = true;
break;
// case '_': Italic();
// case '^': Styles.SuperscriptStyleKey
// case '+': Styles.InsertedStyleKey
// case '=': Styles.MarkedStyleKey
}
}
return base.AddChild(childToAdd, indexInChildrenList);
}
}
/// <summary>
/// A Agg renderer for an <see cref="EmphasisInline"/>.
/// </summary>
/// <seealso cref="EmphasisInline" />
public class AggEmphasisInlineRenderer : AggObjectRenderer<EmphasisInline>
{
protected override void Write(AggRenderer renderer, EmphasisInline obj)
{
//Span span = null;
//switch (obj.DelimiterChar)
//{
// case '*':
// case '_':
// span = obj.IsDouble ? (Span)new Bold() : new Italic();
// break;
// case '~':
// span = new Span();
// span.SetResourceReference(FrameworkContentElement.StyleProperty, obj.IsDouble ? Styles.StrikeThroughStyleKey : Styles.SubscriptStyleKey);
// break;
// case '^':
// span = new Span();
// span.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.SuperscriptStyleKey);
// break;
// case '+':
// span = new Span();
// span.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.InsertedStyleKey);
// break;
// case '=':
// span = new Span();
// span.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.MarkedStyleKey);
// break;
//}
if (true) //span != null)
{
renderer.Push(new EmphasisInlineX(obj.DelimiterChar));
renderer.WriteChildren(obj);
renderer.Pop();
}
else
{
renderer.WriteChildren(obj);
}
}
}
}

View file

@ -1,37 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax.Inlines;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg.Inlines
{
public class LineBreakX : AutoFit, IHardBreak { }
public class LineBreakSoftX : AutoFit{ }
/// <summary>
/// A Agg renderer for a <see cref="LineBreakInline"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Agg.AggObjectRenderer{Markdig.Syntax.Inlines.LineBreakInline}" />
public class AggLineBreakInlineRenderer : AggObjectRenderer<LineBreakInline>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, LineBreakInline obj)
{
if (obj.IsHard)
{
renderer.WriteInline(new LineBreakX()); // new LineBreak());
}
else
{
// TODO: Remove soft - use WriteText
renderer.WriteInline(new LineBreakSoftX()); // new LineBreak());
// Soft line break.
renderer.WriteText(" ");
}
}
}
}

View file

@ -1,297 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using Markdig.Agg;
using Markdig.Syntax.Inlines;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
using MatterHackers.VectorMath;
namespace Markdig.Renderers.Agg.Inlines
{
public class TextLinkX : FlowLayoutWidget
{
private LinkInline linkInline;
private string url;
private AggRenderer aggRenderer;
public TextLinkX(AggRenderer renderer, string url, LinkInline linkInline)
{
this.HAnchor = HAnchor.Fit;
this.VAnchor = VAnchor.Fit;
this.Cursor = Cursors.Hand;
this.linkInline = linkInline;
this.url = url;
this.aggRenderer = renderer;
}
protected override void OnClick(MouseEventArgs mouseEvent)
{
if (linkInline.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
ApplicationController.LaunchBrowser(linkInline.Url);
}
else
{
if (aggRenderer.RootWidget.Parents<MarkdownWidget>().FirstOrDefault() is MarkdownWidget markdownWidget)
{
markdownWidget.LoadUri(new Uri(url));
}
}
base.OnClick(mouseEvent);
}
public override GuiWidget AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
if (childToAdd is TextWidget textWidget)
{
// Underline TextWidget children of TextLink nodes
textWidget.Underline = true;
}
// Allow link parent to own mouse events
childToAdd.Selectable = false;
return base.AddChild(childToAdd, indexInChildrenList);
}
}
public class ImageLinkSimpleX : FlowLayoutWidget
{
private static ImageBuffer icon = StaticData.Instance.LoadIcon("internet.png", 16, 16);
public ImageLinkSimpleX(AggRenderer renderer, string imageUrl, string linkUrl = null)
{
this.HAnchor = HAnchor.Stretch;
this.VAnchor = VAnchor.Fit;
this.Selectable = false;
this.ImageUrl = imageUrl;
this.LinkUrl = linkUrl;
this.aggRenderer = renderer;
if (linkUrl != null)
{
this.Selectable = true;
}
sequenceWidget = new ResponsiveImageSequenceWidget(new ImageSequence(icon))
{
Cursor = Cursors.Hand,
};
sequenceWidget.MaximumSizeChanged += (s, e) =>
{
this.MinStretchOrFitHorizontal(20 * GuiWidget.DeviceScale, sequenceWidget.MaximumSize.X);
if (aggRenderer.RootWidget.Parents<MarkdownWidget>().FirstOrDefault() is MarkdownWidget markdownWidget)
{
markdownWidget.Width += 1;
}
};
sequenceWidget.Click += SequenceWidget_Click;
this.AddChild(sequenceWidget);
}
private void SequenceWidget_Click(object sender, MouseEventArgs e)
{
if (this.LinkUrl != null)
{
if (LinkUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
ApplicationController.LaunchBrowser(LinkUrl);
}
else
{
try
{
if (aggRenderer.RootWidget.Parents<MarkdownWidget>().FirstOrDefault() is MarkdownWidget markdownWidget)
{
markdownWidget.LoadUri(new Uri(LinkUrl));
}
}
catch
{
}
}
}
}
public override void OnDraw(Graphics2D graphics2D)
{
if (!hasBeenLoaded)
{
if (ImageUrl.StartsWith("http"))
{
WebCache.RetrieveImageSquenceAsync(sequenceWidget.ImageSequence, ImageUrl);
}
hasBeenLoaded = true;
}
base.OnDraw(graphics2D);
}
/// <summary>
/// Sets this control to Stretch and all direct parent FlowLayoutWidgets to Stretch, it then ensures
/// this and all direct parent FlowLayouts have a max width of the contents of this.
/// </summary>
/// <param name="absoluteMinWidth">The minimum size will be set to the larger of the existing minimum size or this value.</param>
/// <param name="absoluteMaxWidth">The maximum size will be set to this value.</param>
private void MinStretchOrFitHorizontal(double absoluteMinWidth, double absoluteMaxWidth)
{
this.HAnchor = HAnchor.Stretch;
MinimumSize = new Vector2(Math.Max(absoluteMinWidth, MinimumSize.X), MinimumSize.Y);
MaximumSize = new Vector2(absoluteMaxWidth, MaximumSize.Y);
}
public string ImageUrl { get; }
private string LinkUrl { get; }
private AggRenderer aggRenderer;
private bool hasBeenLoaded;
private ResponsiveImageSequenceWidget sequenceWidget;
}
public class ImageLinkAdvancedX : FlowLayoutWidget
{
private static HttpClient client = new HttpClient();
private static ImageBuffer icon = StaticData.Instance.LoadIcon("internet.png", 16, 16);
public string Url { get; }
public ImageLinkAdvancedX(string url)
{
HAnchor = HAnchor.Fit;
VAnchor = VAnchor.Fit;
this.Url = url;
var imageBuffer = new ImageBuffer(icon);
var imageWidget = new ImageWidget(imageBuffer);
this.AddChild(imageWidget);
try
{
if (url.StartsWith("http"))
{
client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ContinueWith(task =>
{
var response = task.Result;
if (response.IsSuccessStatusCode)
{
response.Content.ReadAsStreamAsync().ContinueWith(streamTask =>
{
// response.Headers.TryGetValues("", s[""] == "" ||
if (string.Equals(Path.GetExtension(url), ".svg", StringComparison.OrdinalIgnoreCase))
{
// Load svg into SvgWidget, swap for ImageWidget
try
{
var svgWidget = new SvgWidget(streamTask.Result, 1)
{
Border = 1,
BorderColor = Color.YellowGreen
};
this.ReplaceChild(imageWidget, svgWidget);
}
catch (Exception svgEx)
{
Debug.WriteLine("Error loading svg: {0} :: {1}", url, svgEx.Message);
}
}
else
{
// Load img
if (!ImageIO.LoadImageData(streamTask.Result, imageBuffer))
{
Debug.WriteLine("Error loading image: " + url);
}
}
});
}
});
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
/// <summary>
/// A Agg renderer for a <see cref="LinkInline"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Agg.AggObjectRenderer{Markdig.Syntax.Inlines.LinkInline}" />
public class AggLinkInlineRenderer : AggObjectRenderer<LinkInline>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, LinkInline link)
{
var url = link.GetDynamicUrl != null ? link.GetDynamicUrl() ?? link.Url : link.Url;
if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
{
url = "#";
}
if (!url.StartsWith("http"))
{
var pageID = url;
url = new Uri(renderer.BaseUri, url).AbsoluteUri;
renderer.ChildLinks.Add(new MarkdownDocumentLink()
{
Uri = new Uri(url),
LinkInline = link,
PageID = pageID
});
}
if (link.IsImage)
{
if (link.Parent is LinkInline linkInLine)
{
renderer.WriteInline(new ImageLinkSimpleX(renderer, url, linkInLine.Url));
}
else
{
renderer.WriteInline(new ImageLinkSimpleX(renderer, url));
}
}
else
{
if (link.FirstChild is LinkInline linkInLine
&& linkInLine.IsImage)
{
renderer.WriteChildren(link);
}
else
{
renderer.Push(new TextLinkX(renderer, url, link));
renderer.WriteChildren(link);
renderer.Pop();
}
}
}
}
}

View file

@ -1,24 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using Markdig.Syntax.Inlines;
namespace Markdig.Renderers.Agg.Inlines
{
/// <summary>
/// A Agg renderer for a <see cref="LiteralInline"/>.
/// </summary>
/// <seealso cref="Markdig.Renderers.Agg.AggObjectRenderer{Markdig.Syntax.Inlines.LiteralInline}" />
public class AggLiteralInlineRenderer : AggObjectRenderer<LiteralInline>
{
/// <inheritdoc/>
protected override void Write(AggRenderer renderer, LiteralInline obj)
{
if (obj.Content.IsEmpty)
return;
renderer.WriteText(ref obj.Content);
}
}
}

View file

@ -1,43 +0,0 @@
/*
Copyright(c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using Markdig.Syntax.Inlines;
namespace Markdig.Agg
{
public class MarkdownDocumentLink
{
public Uri Uri { get; internal set; }
public LinkInline LinkInline { get; internal set; }
public string PageID { get; internal set; }
}
}

View file

@ -1,31 +0,0 @@
// Copyright (c) 2016-2017 Nicolas Musset. All rights reserved.
// This file is licensed under the MIT license.
// See the LICENSE.md file in the project root for more information.
using System;
// ReSharper disable once CheckNamespace
namespace Markdig.Agg
{
/// <summary>
/// Provides extension methods for <see cref="MarkdownPipeline"/> to enable several Markdown extensions.
/// </summary>
public static class MarkdownExtensions
{
/// <summary>
/// Uses all extensions supported by <c>Markdig.Agg</c>.
/// </summary>
/// <param name="pipeline">The pipeline.</param>
/// <returns>The modified pipeline</returns>
public static MarkdownPipelineBuilder UseSupportedExtensions(this MarkdownPipelineBuilder pipeline)
{
if (pipeline == null) throw new ArgumentNullException(nameof(pipeline));
return pipeline
.UseEmphasisExtras()
.UseGridTables()
.UsePipeTables()
.UseTaskLists()
.UseAutoLinks();
}
}
}

View file

@ -1,181 +0,0 @@
/*
Copyright(c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Net;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.VectorMath;
namespace Markdig.Agg
{
public class MarkdownWidget : ScrollableWidget
{
private string _markDownText = null;
private FlowLayoutWidget contentPanel;
private AggMarkdownDocument markdownDocument;
private ThemeConfig theme;
public MarkdownWidget(ThemeConfig theme, Uri contentUri, bool scrollContent = true)
: this(theme, scrollContent)
{
markdownDocument.BaseUri = contentUri;
this.LoadUri(contentUri);
}
public MarkdownWidget(ThemeConfig theme, bool scrollContent = true)
: base(scrollContent)
{
markdownDocument = new AggMarkdownDocument();
this.theme = theme;
this.HAnchor = HAnchor.Stretch;
this.ScrollArea.HAnchor = HAnchor.Stretch;
this.ScrollArea.VAnchor = VAnchor.Fit;
if (scrollContent)
{
this.VAnchor = VAnchor.Stretch;
this.ScrollArea.Margin = new BorderDouble(0, 0, 15, 0);
}
else
{
this.VAnchor = VAnchor.Fit;
}
var lastScroll = this.TopLeftOffset;
this.ScrollPositionChanged += (s, e) =>
{
lastScroll = TopLeftOffset;
};
// make sure as the scrolling area changes height we maintain our current scroll position
this.ScrollArea.BoundsChanged += (s, e) =>
{
TopLeftOffset = lastScroll;
};
contentPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Stretch,
VAnchor = VAnchor.Fit
};
this.AddChild(contentPanel);
}
public override void OnSizeChanged(EventArgs e)
{
contentPanel.Height = contentPanel.Height - 1;
base.OnSizeChanged(e);
}
public void LoadUri(Uri uri, HelpArticle sourceArticle = null)
{
try
{
var webClient = new WebClient();
markdownDocument.BaseUri = uri;
this.sourceArticle = sourceArticle;
try
{
// put in controls from the feed that show relevant printer information
WebCache.RetrieveText(uri.ToString(),
(markDown) =>
{
UiThread.RunOnIdle(() =>
{
this.Markdown = markDown;
});
});
}
catch
{
}
}
catch
{
// On error, revert to empty content
this.Markdown = "";
}
}
private HelpArticle sourceArticle;
/// <summary>
/// Gets or sets the markdown to display.
/// </summary>
public string Markdown
{
get => _markDownText;
set
{
if (_markDownText != value)
{
_markDownText = value;
// Empty self
contentPanel.CloseChildren();
this.Width = 10;
this.ScrollPositionFromTop = Vector2.Zero;
// Add header/edit button for HelpArticle pages
if (sourceArticle != null)
{
var helpArticleHeader = new HelpArticleHeader(sourceArticle, theme, boldFont: true, pointSize: theme.FontSize14, editToolTipText: "Edit Page".Localize());
helpArticleHeader.EditClicked += (s, e) =>
{
ApplicationController.LaunchBrowser($"https://github.com/MatterHackers/MatterControl-Help/blob/master/input/{sourceArticle.Path}");
// ApplicationController.LaunchBrowser($"https://github.com/MatterHackers/MatterControl-Docs/tree/master/docs/Help/{sourceArticle.Path}");
};
contentPanel.AddChild(helpArticleHeader);
}
// Parse and reconstruct
markdownDocument.Markdown = value;
markdownDocument.Parse(contentPanel);
}
}
}
public string MatchingText
{
get => markdownDocument.MatchingText;
set => markdownDocument.MatchingText = value;
}
}
}

View file

@ -1,38 +0,0 @@
/*
Copyright(c) 2019, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using Markdig.Syntax.Inlines;
namespace Markdig.Renderers.Agg
{
public class MatchingTextInline : LeafInline
{
public string MatchingText { get; set; }
}
}

View file

@ -1,71 +0,0 @@
/*
Copyright(c) 2019, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using Markdig.Helpers;
using Markdig.Parsers;
namespace Markdig.Renderers.Agg
{
public class MatchingTextParser : InlineParser
{
private string matchingText;
public MatchingTextParser(string matchingText)
{
this.OpeningCharacters = new[] { matchingText[0] };
this.matchingText = matchingText.ToLower();
}
public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
bool matchFound = slice.MatchLowercase(matchingText);
if (matchFound)
{
int inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column);
processor.Inline = new MatchingTextInline
{
Span =
{
Start = inlineStart,
End = inlineStart + matchingText.Length
},
Line = line,
Column = column,
MatchingText = matchingText
};
slice.Start = inlineStart + matchingText.Length;
}
return matchFound;
}
}
}

View file

@ -1,38 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using Markdig.Extensions.Tables;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
public class AggTable : FlowLayoutWidget
{
public List<AggTableColumn> Columns { get; }
public List<AggTableRow> Rows { get; }
public AggTable(Table table) : base(FlowDirection.TopToBottom)
{
this.Columns = table.ColumnDefinitions.Select(c => new AggTableColumn(c)).ToList();
}
public override void OnLayout(LayoutEventArgs layoutEventArgs)
{
if (this.Columns?.Count > 0)
{
foreach (var column in this.Columns)
{
column.SetCellWidths();
}
}
base.OnLayout(layoutEventArgs);
}
}
}

View file

@ -1,53 +0,0 @@
// 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;
using System.Linq;
using MatterHackers.Agg.UI;
namespace Markdig.Renderers.Agg
{
// Parent container to restrict bounds
public class AggTableCell : GuiWidget
{
public AggTableCell()
{
// TODO: drive from column once width calculation is performed
Width = 300;
Height = 25;
// Use event rather than OnLayout as it only seems to produce the desired effect
this.Layout += AggTableCell_Layout;
}
// TODO: Investigate. Without this solution, child content is wrapped and clipped, leaving only the last text block visible
private void AggTableCell_Layout(object sender, EventArgs e)
{
Console.WriteLine(Parent?.Name);
if (this.Children.Count > 0 && this.Children.First() is FlowLeftRightWithWrapping wrappedChild
&& wrappedChild.Height != this.Height)
{
//using (this.LayoutLock())
{
//// Set height to ensure bounds grow to content after reflow
//this.Height = wrappedChild.Height;
if (this.Parent is AggTableRow parentRow)
{
parentRow.CellHeightChanged(wrappedChild.Height);
}
}
this.ContentWidth = wrappedChild.ContentWidth;
}
}
public double ContentWidth { get; private set; }
// TODO: Use to align child content when bounds are less than current
public HAnchor FlowHAnchor { get; set; }
}
}

View file

@ -1,59 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using Markdig.Extensions.Tables;
namespace Markdig.Renderers.Agg
{
public class AggTableColumn
{
private TableColumnDefinition ColumnDefinition;
public AggTableColumn(TableColumnDefinition definition)
{
this.ColumnDefinition = definition;
}
public List<AggTableCell> Cells { get; } = new List<AggTableCell>();
public void SetCellWidths()
{
double cellPadding = 10;
if (this.Cells.Count == 0)
{
return;
}
// TODO: Column/cell width theortically is:
//
// Case A. Expanding to the maximum content width of cells in column to grow each
// cell to a minimum value.
//
// Case B. Contracting when the aggregate column widths exceed the bounds
// of the parent container.
//
// Case C. Distributing percentages across fixed bounds of the parent container
//
// Other cases...
// This block attempts to implement Case A by finding the max content width per cells in each column
//
// Collect max content widths from each cell in this column
double maxCellWidth = this.Cells.Select(c => c.ContentWidth).Max() + cellPadding * 2;
// Apply max width to cells in this column
foreach (var cell in this.Cells)
{
if (cell.Width != maxCellWidth)
{
cell.Width = maxCellWidth;
}
}
}
}
}

View file

@ -1,91 +0,0 @@
// 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.UI;
namespace Markdig.Renderers.Agg
{
public class AggTableRenderer : AggObjectRenderer<Table>
{
protected override void Write(AggRenderer renderer, Table mdTable)
{
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
if (mdTable == null) throw new ArgumentNullException(nameof(mdTable));
var aggTable = new AggTable(mdTable)
{
Margin = new BorderDouble(top: 12),
};
renderer.Push(aggTable);
foreach (var rowObj in mdTable)
{
var mdRow = (TableRow)rowObj;
var aggRow = new AggTableRow()
{
IsHeadingRow = mdRow.IsHeader,
};
renderer.Push(aggRow);
if (mdRow.IsHeader)
{
// Update to desired header row styling and/or move into AggTableRow for consistency
aggRow.BackgroundColor = MatterHackers.MatterControl.AppContext.Theme.TabBarBackground;
}
for (var i = 0; i < mdRow.Count; i++)
{
var mdCell = (TableCell)mdRow[i];
var aggCell = new AggTableCell();
aggRow.Cells.Add(aggCell);
if (mdTable.ColumnDefinitions.Count > 0)
{
// Grab the column definition, or fall back to a default
var columnIndex = mdCell.ColumnIndex < 0 || mdCell.ColumnIndex >= mdTable.ColumnDefinitions.Count
? i
: mdCell.ColumnIndex;
columnIndex = columnIndex >= mdTable.ColumnDefinitions.Count ? mdTable.ColumnDefinitions.Count - 1 : columnIndex;
aggTable.Columns[columnIndex].Cells.Add(aggCell);
if (mdTable.ColumnDefinitions[columnIndex].Alignment.HasValue)
{
switch (mdTable.ColumnDefinitions[columnIndex].Alignment)
{
case TableColumnAlign.Center:
aggCell.FlowHAnchor |= HAnchor.Center;
break;
case TableColumnAlign.Right:
aggCell.FlowHAnchor |= HAnchor.Right;
break;
case TableColumnAlign.Left:
aggCell.FlowHAnchor |= HAnchor.Left;
break;
}
}
}
renderer.Push(aggCell);
renderer.Write(mdCell);
renderer.Pop();
}
// Pop row
renderer.Pop();
}
// Pop table
renderer.Pop();
}
}
}

View file

@ -1,78 +0,0 @@
// 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;
using System.Collections.Generic;
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.Margin = new BorderDouble(10, 4);
this.VAnchor = VAnchor.Absolute;
this.Height = 25;
}
public bool IsHeadingRow { get; set; }
public List<AggTableCell> Cells { get; } = new List<AggTableCell>();
public double RowHeight { get; private 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);
}
internal void CellHeightChanged(double newHeight)
{
double cellPadding = 2;
double height = newHeight + 2 * cellPadding;
//double maxChildHeight = this.Cells.Select(c => c.Height).Max();
if (this.RowHeight != height)
{
foreach (var cell in this.Cells)
{
using (cell.LayoutLock())
{
cell.Height = height;
}
}
using (this.LayoutLock())
{
this.Height = this.RowHeight = height;
}
}
}
}
}

@ -1 +1 @@
Subproject commit 39d47369081d0434eb7ae0610bc76b71c4e0c210
Subproject commit 8d9c41fda05ae25a84ba5e3483255fb4b4f040b4