Ejemplo n.º 1
0
        public static void AddNewMessageRow(this FlowDocument document, Tox tox, MessageData data, bool sameUser)
        {
            document.IsEnabled = true;

            //Make a new row
            TableRow newTableRow = new TableRow();
            newTableRow.Tag = data;

            //Make a new cell and create a paragraph in it
            TableCell usernameTableCell = new TableCell();
            usernameTableCell.Name = "usernameTableCell";
            usernameTableCell.Padding = new Thickness(10, 0, 0, 0);

            Paragraph usernameParagraph = new Paragraph();
            usernameParagraph.TextAlignment = data.IsAction ? TextAlignment.Right : TextAlignment.Left;
            usernameParagraph.Foreground = new SolidColorBrush(Color.FromRgb(164, 164, 164));

            if (data.Username != tox.Name.Replace("\n", "").Replace("\r", ""))
                usernameParagraph.SetResourceReference(Paragraph.ForegroundProperty, "AccentColorBrush");

            if(!sameUser)
                usernameParagraph.Inlines.Add(data.Username);

            usernameTableCell.Blocks.Add(usernameParagraph);

            //Make a new cell and create a paragraph in it
            TableCell messageTableCell = new TableCell();
            Paragraph messageParagraph = new Paragraph();
            messageParagraph.TextAlignment = TextAlignment.Left;

            if (!data.IsGroupMsg && data.IsSelf)
                messageParagraph.Foreground = Brushes.LightGray;

            bool isHighlight = data.IsGroupMsg && !data.IsSelf && data.Message.ToLower().Contains(tox.Name.ToLower());
            ProcessMessage(data, messageParagraph, false, isHighlight);

            messageTableCell.Blocks.Add(messageParagraph);

            TableCell timestampTableCell = new TableCell();
            Paragraph timestampParagraph = new Paragraph();
            timestampParagraph.Foreground = Brushes.LightGray;
            timestampTableCell.TextAlignment = TextAlignment.Right;
            timestampParagraph.Inlines.Add(data.Timestamp.ToShortTimeString());
            timestampTableCell.Blocks.Add(timestampParagraph);

            //Add the two cells to the row we made before
            newTableRow.Cells.Add(usernameTableCell);
            newTableRow.Cells.Add(messageTableCell);
            newTableRow.Cells.Add(timestampTableCell);

            //Adds row to the Table > TableRowGroup
            TableRowGroup MessageRows = (TableRowGroup)document.FindName("MessageRows");
            MessageRows.Rows.Add(newTableRow);
        }
Ejemplo n.º 2
0
        public static Paragraph Present(IConferenceMessage message)
        {
            Paragraph paragraph = new Paragraph();
            paragraph.SetResourceReference(Paragraph.StyleProperty, "parentRowStyle");

            // at first, textInlines will contains only one inline - raw text
            List<Inline> textInlines = new List<Inline>();

            // applying custom decorators
            DecoratorsRegistry.GetDecorators().ForEach(i => textInlines = i.Decorate(message, textInlines));

            paragraph.Inlines.AddRange(textInlines);

            return paragraph;
        }
Ejemplo n.º 3
0
        public static void AddNewMessageRow(this FlowDocument document, Tox tox, MessageData data, EmojiProvider emojiProvider)
        {
            document.IsEnabled = true;

            //Make a new row
            TableRow newTableRow = new TableRow();

            //Make a new cell and create a paragraph in it
            TableCell usernameTableCell = new TableCell();
            usernameTableCell.Name = "usernameTableCell";
            usernameTableCell.Padding = new Thickness(10, 0, 0, 0);

            Paragraph usernameParagraph = new Paragraph();
            usernameParagraph.TextAlignment = data.IsAction ? TextAlignment.Right : TextAlignment.Left;
            usernameParagraph.Foreground = new SolidColorBrush(Color.FromRgb(164, 164, 164));

            if (data.Username != tox.GetSelfName())
                usernameParagraph.SetResourceReference(Paragraph.ForegroundProperty, "AccentColorBrush");

            usernameParagraph.Inlines.Add(data.Username);
            usernameTableCell.Blocks.Add(usernameParagraph);

            //Make a new cell and create a paragraph in it
            TableCell messageTableCell = new TableCell();
            Paragraph messageParagraph = new Paragraph();
            messageParagraph.TextAlignment = TextAlignment.Left;

            ProcessMessage(data, messageParagraph, false, emojiProvider);

            //messageParagraph.Inlines.Add(fakeHyperlink);
            messageTableCell.Blocks.Add(messageParagraph);

            TableCell timestampTableCell = new TableCell();
            Paragraph timestamParagraph = new Paragraph();
            timestampTableCell.TextAlignment = TextAlignment.Right;
            timestamParagraph.Inlines.Add(DateTime.Now.ToShortTimeString());
            timestampTableCell.Blocks.Add(timestamParagraph);
            timestamParagraph.Foreground = new SolidColorBrush(Color.FromRgb(164, 164, 164));
            //Add the two cells to the row we made before
            newTableRow.Cells.Add(usernameTableCell);
            newTableRow.Cells.Add(messageTableCell);
            newTableRow.Cells.Add(timestampTableCell);

            //Adds row to the Table > TableRowGroup
            TableRowGroup MessageRows = (TableRowGroup)document.FindName("MessageRows");
            MessageRows.Rows.Add(newTableRow);
        }
        //=====================================================================

        /// <summary>
        /// Handle table elements
        /// </summary>
        /// <param name="props">The element properties</param>
        private static void TableElement(ElementProperties props)
        {
            // If there is a title element, add a title using its content right before the table.  The title
            // element handler will ignore it since it will have this table as its parent.
            XElement title = props.Element.Element(ddue + "title");

            if(title != null)
            {
                Paragraph p = new Paragraph(new Run(reCondenseWhitespace.Replace(title.Value.Trim(), " ")));
                props.Converter.AddNonParentToBlockContainer(p);

                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.TableTitle);
            }

            props.Converter.AddToBlockContainer(new Table());
        }
        /// <summary>
        /// This is used to add the related topic links
        /// </summary>
        /// <param name="converter">The converter used to add the elements</param>
        /// <param name="s">The section used to contain the links</param>
        /// <param name="links">The list of links to add</param>
        /// <param name="sectionTitle">The section title</param>
        private static void AddRelatedTopicLinks(MamlToFlowDocumentConverter converter, Section s,
          List<XElement> links, string sectionTitle)
        {
            Paragraph p;
            bool isFirst = true;

            if(links.Count != 0)
            {
                p = new Paragraph(new Run(sectionTitle));
                s.Blocks.Add(p);
                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.RelatedTopicTitle);

                p = new Paragraph();
                s.Blocks.Add(p);
                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.NoTopMargin);

                foreach(var link in links)
                {
                    if(isFirst)
                        isFirst = false;
                    else
                        p.Inlines.Add(new LineBreak());

                    converter.ParseChildren(p, new[] { link });
                }
            }
        }
        /// <summary>
        /// Handle related topics elements
        /// </summary>
        /// <param name="props">The element properties</param>
        /// <remarks>If empty, the related topics section is omitted</remarks>
        private static void RelatedTopicsElement(ElementProperties props)
        {
            List<XElement> tasks = new List<XElement>(), reference = new List<XElement>(),
                concepts = new List<XElement>(), otherResources = new List<XElement>(),
                tokenContent = new List<XElement>();
            XElement token;
            XAttribute attribute;
            Guid topicId, href;
            string linkType;

            if(!props.ParseChildren || !props.Element.HasElements)
            {
                props.ParseChildren = props.ReturnToParent = false;
                return;
            }

            // All links are handled here
            props.ParseChildren = false;

            // A name is added here for use by autoOutline elements
            Section s = new Section { Name = ToElementName("seeAlsoSection") };
            props.Converter.AddToBlockContainer(s);

            // Add the section title
            Paragraph p = new Paragraph(new Run(NamedSectionTitles[props.Element.Name.LocalName]));
            s.Blocks.Add(p);
            p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.Title);

            // Expand tokens first
            foreach(var link in props.Element.Nodes().OfType<XElement>().Where(n => n.Name.LocalName == "token"))
                if(props.Converter.Tokens.TryGetValue(link.Value.Trim(), out token))
                    tokenContent.AddRange(token.Nodes().OfType<XElement>());

            // Group the elements by type or topic ID
            foreach(var link in props.Element.Nodes().OfType<XElement>().Concat(tokenContent))
            {
                linkType = link.Name.LocalName;
                attribute = link.Attribute("topicType_id");

                if(attribute == null || !Guid.TryParse(attribute.Value, out topicId))
                    topicId = Guid.Empty;

                attribute = link.Attribute(xlink + "href");

                if(attribute == null || !Guid.TryParse(attribute.Value, out href))
                    href = Guid.Empty;

                if(href != Guid.Empty && (linkType == "link" || linkType == "legacyLink") && (
                  topicId == HowToId || topicId == WalkthroughId || topicId == SampleId ||
                  topicId == TroubleshootingId))
                {
                    tasks.Add(link);
                }
                else
                    if(linkType == "codeEntityReference" || ((linkType == "link" || linkType == "legacyLink") && (
                      href == Guid.Empty || topicId == ReferenceWithoutSyntaxId ||
                      topicId == ReferenceWithSyntaxId || topicId == XmlReferenceId ||
                      topicId == ErrorMessageId || topicId == UIReferenceId)))
                    {
                        reference.Add(link);
                    }
                    else
                        if(href != Guid.Empty && (linkType == "link" || linkType == "legacyLink") && (
                          topicId == ConceptualId || topicId == SdkTechnologyOverviewArchitectureId ||
                          topicId == SdkTechnologyOverviewCodeDirectoryId ||
                          topicId == SdkTechnologyOverviewScenariosId ||
                          topicId == SdkTechnologyOverviewTechnologySummaryId))
                            concepts.Add(link);
                        else
                            if(linkType == "externalLink" || ((linkType == "link" || linkType == "legacyLink") &&
                              href != Guid.Empty && (topicId == Guid.Empty || topicId == OrientationId ||
                              topicId == WhitePaperId || topicId == CodeEntityId || topicId == GlossaryId ||
                              topicId == SDKTechnologyOverviewOrientationId)))
                                otherResources.Add(link);
            }

            // Add each set
            AddRelatedTopicLinks(props.Converter, s, tasks, "Tasks");
            AddRelatedTopicLinks(props.Converter, s, reference, "Reference");
            AddRelatedTopicLinks(props.Converter, s, concepts, "Concepts");
            AddRelatedTopicLinks(props.Converter, s, otherResources, "Other Resources");
        }
        //=====================================================================

        /// <summary>
        /// Handle defined term elements
        /// </summary>
        /// <param name="props">The element properties</param>
        private static void DefinedTermElement(ElementProperties props)
        {
            Paragraph p = new Paragraph();
            props.Converter.AddToBlockContainer(p);
            p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.DefinedTerm);
        }
        /// <summary>
        /// Handle title elements
        /// </summary>
        /// <param name="props">The element properties</param>
        /// <remarks>If the title element is inside a table, it is skipped as the table will already have
        /// added it outside of itself.</remarks>
        private static void TitleElement(ElementProperties props)
        {
            if(props.Converter.CurrentBlockElement is Table)
                props.ReturnToParent = false;
            else
            {
                Paragraph p = new Paragraph(new Run(reCondenseWhitespace.Replace(
                    props.Element.Value.Trim(), " ")));
                props.Converter.AddToBlockContainer(p);
                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.Title);
            }

            props.ParseChildren = false;
        }
        /// <summary>
        /// Handle general and named section elements
        /// </summary>
        /// <param name="props">The element properties</param>
        /// <remarks>If the section is empty, it will be omitted</remarks>
        private static void SectionElement(ElementProperties props)
        {
            if(props.ParseChildren && props.Element.HasElements)
            {
                Section s = new Section();
                string title;

                // If this is a named section, add the standard title
                if(NamedSectionTitles.TryGetValue(props.Element.Name.LocalName, out title))
                {
                    Paragraph p = new Paragraph(new Run(title));
                    s.Blocks.Add(p);
                    p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.Title);
                }

                props.Converter.AddToBlockContainer(s);
            }
            else
                props.ParseChildren = props.ReturnToParent = false;
        }
        //=====================================================================

        /// <summary>
        /// Handle alert elements
        /// </summary>
        /// <param name="props">The element properties</param>
        private static void AlertElement(ElementProperties props)
        {
            XAttribute attribute;
            string title = null, icon = null;

            // Map the class name to a title
            attribute = props.Element.Attribute("class");

            if(attribute == null || !AlertTitles.TryGetValue(attribute.Value, out title))
                title = "Note";

            if(attribute == null || !AlertIcons.TryGetValue(attribute.Value, out icon))
                icon = "AlertNote";

            Section alert = new Section();
            props.Converter.AddToBlockContainer(alert);

            Paragraph p = new Paragraph();
            alert.Blocks.Add(p);

            // Set the icon based on the alert type
            var iconImage = (ImageSource)props.Converter.Document.Resources[icon];

            p.Inlines.Add(new InlineUIContainer(new Image
            {
                Source = iconImage,
                Height = iconImage.Height / 2,
                Width = iconImage.Width / 2,
                ToolTip = title,
                Margin = new Thickness(0, 0, 5, 0),
                VerticalAlignment = VerticalAlignment.Center
            }));

            p.Inlines.Add(new Run(title));
            p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.AlertTitle);

            Section alertBody = new Section();
            alert.Blocks.Add(alertBody);

            // We want the body section to be the current parent here rather than the containing section
            props.Converter.CurrentBlockElement = alertBody;

            alertBody.SetResourceReference(Section.StyleProperty, NamedStyle.AlertBody);
        }
        /// <summary>
        /// This is used to render a glossary division
        /// </summary>
        /// <param name="d">The root glossary division element</param>
        /// <param name="divisionId">The division ID used as a prefix for each letter section in the division</param>
        /// <param name="entries">An enumerable list of all glossary entries</param>
        /// <param name="converter">The converter to which the glossary elements will be added</param>
        /// <returns>An enumerable list of blocks that define the glossary division in the document</returns>
        private static void RenderGlossaryDivision(XElement d, string divisionId,
          IEnumerable<GlossaryEntry> entries, MamlToFlowDocumentConverter converter)
        {
            Section s;
            Paragraph p = new Paragraph();
            bool isFirst = true;

            // Group all entries in this division by the first letter of the first term
            var groupLetters = entries.Where(g => g.Parent == d).GroupBy(
                g => Char.ToUpperInvariant(g.Terms.First().Key[0])).OrderBy(g => g.Key);

            // Generate the letter bar for the division
            for(char ch = 'A'; ch <= 'Z'; ch++)
            {
                if(isFirst)
                    isFirst = false;
                else
                    p.Inlines.Add(new Run(" | "));

                if(!groupLetters.Any(g => g.Key == ch))
                    p.Inlines.Add(new Bold(new Run(ch.ToString())));
                else
                    p.Inlines.Add(new Hyperlink(new Run(ch.ToString()))
                    {
                        NavigateUri = new Uri("link://#" + divisionId + "_" + ch.ToString())
                    });
            }

            converter.AddNonParentToBlockContainer(p);
            p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.GlossaryLetterBar);

            foreach(var g in groupLetters)
            {
                p = new Paragraph(new Run(g.Key.ToString())
                {
                    Name = ToElementName(divisionId + "_" + g.Key.ToString())
                });

                converter.AddNonParentToBlockContainer(p);
                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.GlossaryLetterTitle);

                foreach(var entry in g)
                {
                    s = new Section();

                    converter.AddNonParentToBlockContainer(s);
                    s.SetResourceReference(Section.StyleProperty, NamedStyle.GlossaryDefinition);

                    p = new Paragraph();
                    isFirst = true;

                    foreach(var t in entry.Terms)
                    {
                        if(isFirst)
                            isFirst = false;
                        else
                            p.Inlines.Add(new Run(", "));

                        p.Inlines.Add(new Bold(new Run(t.Key))
                        {
                            Name = (t.Value == null) ? String.Empty : ToElementName(t.Value)
                        });
                    }

                    s.Blocks.Add(p);
                    p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.NoMargin);

                    converter.ParseChildren(s, entry.Definition.Nodes());

                    if(entry.RelatedEntries.Count != 0)
                    {
                        p = new Paragraph();
                        p.Inlines.Add(new Run("See also: "));
                        isFirst = true;

                        foreach(var r in entry.RelatedEntries)
                        {
                            if(isFirst)
                                isFirst = false;
                            else
                                p.Inlines.Add(new Run(", "));

                            var related = entries.SelectMany(e => e.Terms).FirstOrDefault(t => t.Value == r);

                            if(related.Key != null)
                                p.Inlines.Add(new Hyperlink(new Run(related.Key))
                                {
                                    NavigateUri = new Uri("link://#" + r)
                                });
                        }

                        p.Inlines.Add(new LineBreak());
                        s.Blocks.Add(p);
                    }
                }
            }
        }
        //=====================================================================

        /// <summary>
        /// Handle all aspects of glossary element and sub-element formatting
        /// </summary>
        /// <param name="props">The element properties</param>
        private static void GlossaryElement(ElementProperties props)
        {
            Section glossary = new Section();
            Paragraph p = null;
            XElement titleElement;
            XAttribute addressAttr;
            List<XElement> divisions;
            Dictionary<XElement, Tuple<string, string>> divisionIds = new Dictionary<XElement, Tuple<string, string>>();
            List<GlossaryEntry> entries = new List<GlossaryEntry>();
            string address, id, title;
            bool isFirst = true;
            int autoId = 1;

            // All elements are handled here
            props.ParseChildren = false;
            props.Converter.AddToBlockContainer(glossary);

            // If there is a title element, add a title using its content
            titleElement = props.Element.Element(ddue + "title");

            if(titleElement != null)
            {
                p = new Paragraph(new Run(reCondenseWhitespace.Replace(titleElement.Value.Trim(), " ")));
                glossary.Blocks.Add(p);

                p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.Title);
            }

            // See if there are divisions.  If so, add one section for each division.  If not, lump all entries
            // into one untitled division.
            divisions = props.Element.Descendants(ddue + "glossaryDiv").ToList();

            // If there are multiple divisions, add a link to each one provided we have an address and a title
            if(divisions.Count == 0)
            {
                divisions = new List<XElement>() { props.Element };
                divisionIds.Add(props.Element, Tuple.Create<string, string>(null, null));
            }
            else
            {
                foreach(var d in divisions)
                {
                    addressAttr = d.Attribute("address");
                    titleElement = d.Element(ddue + "title");

                    if(addressAttr != null)
                    {
                        address = addressAttr.Value;
                        id = ToElementName(address);
                    }
                    else
                        address = id = null;

                    if(titleElement != null)
                        title = reCondenseWhitespace.Replace(titleElement.Value.Trim(), " ");
                    else
                        title = null;

                    divisionIds.Add(d, Tuple.Create(id, title));

                    if(!String.IsNullOrEmpty(title))
                    {
                        if(isFirst)
                        {
                            p = new Paragraph();
                            glossary.Blocks.Add(p);
                            isFirst = false;
                        }
                        else
                            p.Inlines.Add(new Run(" | "));

                        if(!String.IsNullOrEmpty(address))
                            p.Inlines.Add(new Hyperlink(new Run(title)) { NavigateUri = new Uri("link://#" + address) });
                        else
                            p.Inlines.Add(new Bold(new Run(title)));
                    }
                }

                p.Inlines.Add(new LineBreak());
            }

            // Extract all glossary entries for use in creating the divisions.  Entries may refer to related
            // entries in other divisions so we need to get them all up front.
            entries.AddRange(props.Element.Descendants(
                MamlToFlowDocumentConverter.ddue + "glossaryEntry").Select(g => new GlossaryEntry(g)));

            // Render each division
            foreach(var d in divisions)
            {
                var titleAndId = divisionIds[d];

                // Add a title if there is one
                if(!String.IsNullOrEmpty(titleAndId.Item2))
                {
                    id = titleAndId.Item1;
                    p = new Paragraph(new Run(titleAndId.Item2)) { Name = id };
                    glossary.Blocks.Add(p);
                    p.SetResourceReference(Paragraph.StyleProperty, NamedStyle.GlossaryDivisionTitle);
                }
                else
                {
                    id = "__GlossaryDiv" + autoId.ToString(CultureInfo.InvariantCulture);
                    autoId++;
                }

                RenderGlossaryDivision(d, id, entries, props.Converter);

                glossary.Blocks.Add(new Paragraph());
            }
        }
Ejemplo n.º 13
0
        private Paragraph ParseChatNodesIntoParagraph(ChatNode[] nodes)
        {
            Paragraph fullElement = new Paragraph();
            foreach (ChatNode node in nodes)
            {
                Inline child = RenderNode(node);
                fullElement.Inlines.Add(child);
            }

            fullElement.Style = display.Resources["Paragraphs"] as Style;
            fullElement.SetResourceReference(FrameworkContentElement.StyleProperty, "Paragraphs");

            return fullElement;
        }