19 using Avalonia.Controls;
20 using Avalonia.Controls.ApplicationLifetimes;
21 using Avalonia.Markup.Xaml;
22 using Avalonia.Threading;
26 using System.Collections.Generic;
126 private double lastRenderedWidth =
double.NaN;
128 private bool initialized =
false;
135 InitializeComponent();
137 this.initialized =
true;
138 ImageCache.SetExitEventHandler();
142 protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
144 base.OnPropertyChanged(change);
146 if (this.initialized)
154 forcedRerender =
true;
160 forcedRerender =
true;
165 MarkdownDocument document = Markdig.Markdown.Parse(change.NewValue.GetValueOrDefault<
string>(),
new MarkdownPipelineBuilder().UseGridTables().UsePipeTables().UseEmphasisExtras().UseGenericAttributes().UseAutoIdentifiers().UseAutoLinks().UseTaskLists().UseListExtras().UseCitations().UseMathematics().UseSmartyPants().Build());
170 this.FindControl<ScrollViewer>(
"ScrollViewer").VerticalContentAlignment = this.VerticalContentAlignment;
174 this.FindControl<ScrollViewer>(
"ScrollViewer").HorizontalContentAlignment = this.HorizontalContentAlignment;
179 private bool forcedRerender =
false;
181 private void Render()
187 if (forcedRerender ||
double.IsNaN(lastRenderedWidth) || width != lastRenderedWidth && width < lastRenderedWidth - MinVariation || width > lastRenderedWidth +
MinVariation)
190 Dictionary<string, string> linkDestinations;
198 pag =
new Page(width, 0);
199 linkDestinations =
new Dictionary<string, string>();
202 Dictionary<string, Delegate> taggedActions =
new Dictionary<string, Delegate>();
203 Dictionary<string, Avalonia.Point> linkDestinationPoints =
new Dictionary<string, Avalonia.Point>();
205 foreach (KeyValuePair<string, string> linkDestination
in linkDestinations)
207 string url = linkDestination.Value;
209 taggedActions.Add(linkDestination.Key, (Func<
RenderAction, IEnumerable<RenderAction>>)(act =>
211 act.PointerEnter += (s, e) =>
213 act.Parent.Cursor =
new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand);
216 act.PointerLeave += (s, e) =>
218 act.Parent.Cursor =
new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Arrow);
221 act.PointerPressed += (s, e) =>
223 if (url.StartsWith(
"#"))
225 if (linkDestinationPoints.TryGetValue(url.Substring(1), out Avalonia.Point target))
227 ScrollViewer scrollViewer = this.FindControl<ScrollViewer>(
"ScrollViewer");
229 scrollViewer.Offset =
new Vector(Math.Max(Math.Min(scrollViewer.Offset.X, target.X), target.X - scrollViewer.Viewport.Width), target.Y);
234 System.Diagnostics.Process.Start(
new System.Diagnostics.ProcessStartInfo() { FileName = url, UseShellExecute = true });
240 linkDestinationPoints[linkDestination.Key] = act.Geometry.Bounds.TopLeft.Transform(act.Transform);
244 linkDestinationPoints[linkDestination.Key] = act.Text.Bounds.TopLeft.Transform(act.Transform);
248 linkDestinationPoints[linkDestination.Key] = act.ImageDestination.Value.TopLeft.Transform(act.Transform);
254 if (url.StartsWith(
"#"))
256 if (!taggedActions.ContainsKey(url.Substring(1)))
258 taggedActions.Add(url.Substring(1), (Func<RenderAction, IEnumerable<RenderAction>>)(act =>
262 linkDestinationPoints[url.Substring(1)] = act.Geometry.Bounds.TopLeft.Transform(act.Transform);
266 linkDestinationPoints[url.Substring(1)] = act.Text.Bounds.TopLeft.Transform(act.Transform);
270 linkDestinationPoints[url.Substring(1)] = act.ImageDestination.Value.TopLeft.Transform(act.Transform);
279 Avalonia.Controls.Canvas can = pag.PaintToCanvas(
false, taggedActions,
false, this.
TextConversionOption);
281 this.FindControl<ScrollViewer>(
"ScrollViewer").Content = can;
282 this.FindControl<ScrollViewer>(
"ScrollViewer").Padding =
new Thickness(0, 0, 0, 0);
283 lastRenderedWidth = width;
284 forcedRerender =
false;
288 this.FindControl<ScrollViewer>(
"ScrollViewer").Padding =
new Thickness(0, 0, width - lastRenderedWidth, 0);
293 private void InitializeComponent()
295 AvaloniaXamlLoader.Load(
this);