Exemplo n.º 1
0
        private static void CreateElement(InlineCollection parent, Node node, RichTextBlockStatus status)
        {
            switch (node)
            {
                case Element element:
                    switch (element.TagName.ToLower())
                    {
                        case "a":
                            {
                                // We want to change BaseUri easily, so we use `GetAttribute("href")` instead of `HtmlAnchorElement.Href`
                                var href = element.GetAttribute("href");

                                if (!status.TryCreateUri(href, out var uri))
                                    break;

                                parent.Add(new Run() { Text = " " });

                                var hyperlink = new Hyperlink()
                                {
                                    NavigateUri = uri,
                                    Foreground = status.Foreground
                                };

                                foreach (var child in element.ChildNodes)
                                {
                                    switch (child)
                                    {
                                        case HtmlImageElement childElement:
                                            if (CreateImage(element, status) is Image image)
                                            {
                                                if (hyperlink.Inlines.Count != 0)
                                                {
                                                    hyperlink.SetUri(href);
                                                    status.Hyperlinks.Add(hyperlink);
                                                    parent.Add(hyperlink);
                                                }

                                                var button = new HyperlinkButton()
                                                {
                                                    NavigateUri = uri,
                                                    Content = image,
                                                    RequestedTheme = status.RequestedTheme
                                                };
                                                button.SetUri(href);
                                                status.HyperlinkButtons.Add(button);
                                                parent.Add(new InlineUIContainer() { Child = button });

                                                hyperlink = new Hyperlink()
                                                {
                                                    NavigateUri = uri,
                                                    Foreground = status.Foreground
                                                };
                                            }
                                            break;
                                        default:
                                            CreateElement(hyperlink.Inlines, child, status);
                                            break;
                                    }
                                    break;
                                }

                                if (hyperlink.Inlines.Count != 0)
                                {
                                    hyperlink.SetUri(href);
                                    status.Hyperlinks.Add(hyperlink);
                                    parent.Add(hyperlink);
                                }

                                parent.Add(new Run() { Text = " " });
                            }
                            break;
                        case "img":
                            {
                                if (CreateImage(element, status) is Image image)
                                    parent.Add(new InlineUIContainer() { Child = image });
                            }
                            break;
                        case "strong":
                        case "b":
                            {
                                var span = new Span() { FontWeight = FontWeights.Bold };
                                CreateChildren(span.Inlines, element, status);
                                parent.Add(span);
                            }
                            break;
                        case "div":
                        case "font":
                        case "p":
                        case "span":
                            {
                                var span = new Span();
                                foreach (var s in ParseStyle(element.GetAttribute("style")))
                                    switch (s.Key)
                                    {
                                        case "font-size":
                                            {
                                                var value = s.Value;

                                                double fontSize;
                                                if (value.EndsWith("px"))
                                                    fontSize = double.Parse(value.Remove(value.Length - 2));
                                                else if (value.EndsWith("%"))
                                                    fontSize = 14 * double.Parse(value.Remove(value.Length - 1)) / 100;
                                                else
                                                    fontSize = 14 * double.Parse(value);

                                                span.FontSize = fontSize;
                                            }
                                            break;
                                        case "font-weight":
                                            switch (s.Value)
                                            {
                                                case "bold":
                                                    span.FontWeight = FontWeights.Bold;
                                                    break;
                                            }
                                            break;
                                    }

                                CreateChildren(span.Inlines, element, status);
                                parent.Add(span);
                            }
                            break;
                        case "br":
                            if (element.NextSibling is Text nextText &&
                                nextText.Data.StartsWith("\n"))
                                break;

                            parent.Add(new LineBreak());
                            break;
                        case "hr":
                            parent.Add(new LineBreak());

                            var line = new Border()
                            {
                                BorderThickness = new Thickness(0, 1, 0, 0),
                                BorderBrush = status.Foreground,
                                Margin = new Thickness(8, 0, 8, 0),
                                Height = 1,
                            };

                            if (status.ActualWidth > 16)
                                line.Width = status.ActualWidth - 16;

                            status.Lines.Add(line);
                            parent.Add(new InlineUIContainer() { Child = line });

                            parent.Add(new LineBreak());
                            break;
                        case "iframe": // Ignore
                        case "script":
                        case "noscript":
                            break;
#if DEBUG
                        default:
                            Debug.WriteLine($"Ignore unknown tag {element.TagName}");
                            break;
#endif

                    }
                    break;
                case Text text:
                    parent.Add(new Run() { Text = text.Data });
                    break;
            }
        }