/// <summary> /// Access set to private to prevent usage from outside. Called only by /// XamlNode constructors. /// </summary> /// <exception cref="ArgumentException"> /// Thrown when one or more arguments have unsupported or illegal values. /// </exception> /// <exception cref="ApplicationException"> /// Thrown when an Application error condition occurs. /// </exception> /// <param name="newStartTag"> /// The new start tag. /// </param> /// <param name="parent"> /// The parent. /// </param> private XamlNode(XamlTag newStartTag, XamlNode parent) { logger.Trace("Entered XamlNode()"); if (newStartTag.TagType == XamlTagType.Unknown) { throw new ArgumentException("The startingTag given is invalid.", "newStartTag"); } if (newStartTag.TagType == XamlTagType.Ending) { throw new ArgumentException("And ending tag was given instead of a starting tag.", "newStartTag"); } this.startTag = newStartTag; this.parent = parent; if (newStartTag.TagType == XamlTagType.SelfClosing) { // Self closing tags have no children or separate closing tags. this.endTag = newStartTag; return; } while (tagMatchesEnumerator.MoveNext()) { var childTag = new XamlTag(tagMatchesEnumerator.Current); if (childTag.TagType == XamlTagType.Ending) { if (childTag.Name != this.Name) { throw new ArgumentException( string.Format("Expected \"{0}\" for end tag, but encountered \"{1}.\"", this.Name, childTag.Name)); } this.endTag = childTag; return; } var childNode = new XamlNode(childTag, this) { DocumentText = this.documentText }; this.ChildrenContainer.AddLast(childNode); } // the end of tags represent the end of xaml tags. Since this builds a // child, it should never reach this point. throw new ApplicationException("Premature end of tags encountered."); }
/// <summary> /// Initializes a new instance of the XamlNode class. used to create a /// root node. /// </summary> /// <exception cref="ApplicationException"> /// Thrown when an Application error condition occurs. /// </exception> /// <param name="documentText"> /// The document text. /// </param> /// <remarks> /// Create the root node of a xaml file with this constructor. All other /// child nodes will be created as a result. /// </remarks> public XamlNode(string documentText) { // The document to be parsed for building a XamlNode tree. this._documentText = documentText; this._isRoot = true; // This object holds a sorted list of Match objects that correspond // to each tag in the document. _sortedTagMatches = new SortedSet <Match>(new XamlTagMatchComparer()); MatchCollection matches = Regex.Matches(documentText, XmlHelpers.STARTTAG_PATTERN, RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.IgnoreCase); foreach (Match item in matches) { _sortedTagMatches.Add(item); } matches = Regex.Matches(documentText, XmlHelpers.ENDTAG_PATTERN, RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.IgnoreCase); foreach (Match item in matches) { _sortedTagMatches.Add(item); } // the _sortedTagMatches collection is complete. That is now used // to build out the tree starting with this node, the root node. _tagMatchesEnumerator = _sortedTagMatches.GetEnumerator(); if (_tagMatchesEnumerator.MoveNext()) { this._startTag = new XamlTag(_tagMatchesEnumerator.Current); if (this._startTag.TagType != XamlTagType.Starting) { throw new ApplicationException("Starting tag expected."); } } else { throw new ApplicationException("Unable to enumerate Xaml tags."); } // Except for this node's end tag, the only thing it will see in // this loop are its children node. The child nodes work similarly, // so by the time they return, the nodes that belong to the children // will be consumed. while (_tagMatchesEnumerator.MoveNext()) { var childTag = new XamlTag(_tagMatchesEnumerator.Current); if (childTag.TagType == XamlTagType.Unknown) { throw new ApplicationException("Unknown tag type encountered."); } if (childTag.TagType == XamlTagType.Ending) { this._endTag = childTag; // This is the end of the root node, so this should be the end // of the xaml tags. if (_tagMatchesEnumerator.MoveNext()) { throw new ApplicationException("Closing tag encountered before last tag."); } break; } var childNode = new XamlNode(childTag, this) { DocumentText = this._documentText }; this.ChildrenContainer.AddLast(childNode); } _tagMatchesEnumerator.Dispose(); _sortedTagMatches = null; }
internal static bool ConvertTagToNodeType(XamlTag xamlTag, ref DocumentNodeType documentNodeType) { documentNodeType = DocumentNodeType.dnUnknown; switch (xamlTag) { default: case XamlTag.XTUnknown: return false; case XamlTag.XTInline: case XamlTag.XTItalic: case XamlTag.XTUnderline: case XamlTag.XTBold: documentNodeType = DocumentNodeType.dnInline; break; case XamlTag.XTHyperlink: documentNodeType = DocumentNodeType.dnHyperlink; break; case XamlTag.XTLineBreak: documentNodeType = DocumentNodeType.dnLineBreak; break; case XamlTag.XTInlineUIContainer: documentNodeType = DocumentNodeType.dnInlineUIContainer; break; case XamlTag.XTBlockUIContainer: documentNodeType = DocumentNodeType.dnBlockUIContainer; break; case XamlTag.XTImage: documentNodeType = DocumentNodeType.dnImage; break; case XamlTag.XTParagraph: documentNodeType = DocumentNodeType.dnParagraph; break; case XamlTag.XTSection: documentNodeType = DocumentNodeType.dnSection; break; case XamlTag.XTList: documentNodeType = DocumentNodeType.dnList; break; case XamlTag.XTListItem: documentNodeType = DocumentNodeType.dnListItem; break; case XamlTag.XTTable: documentNodeType = DocumentNodeType.dnTable; break; case XamlTag.XTTableBody: documentNodeType = DocumentNodeType.dnTableBody; break; case XamlTag.XTTableRow: documentNodeType = DocumentNodeType.dnRow; break; case XamlTag.XTTableCell: documentNodeType = DocumentNodeType.dnCell; break; } return true; }
internal static bool ConvertToTag(ConverterState converterState, string tagName, ref XamlTag xamlTag) { if (tagName.Length == 0) { return false; } xamlTag = (XamlTag)BasicLookup(TagTable, tagName); return xamlTag != XamlTag.XTUnknown; }
// Helper for IXamlContentHandler.StartElement. private XamlToRtfError HandleAttributes(ConverterState converterState, IXamlAttributes attributes, DocumentNode documentNode, XamlTag xamlTag, DocumentNodeArray dna) { int nLen = 0; XamlToRtfError xamlToRtfError = attributes.GetLength(ref nLen); if (xamlToRtfError == XamlToRtfError.None) { string uri = string.Empty; string newLocalName = string.Empty; string newQName = string.Empty; string valueString = string.Empty; FormatState formatState = documentNode.FormatState; XamlAttribute attribute = XamlAttribute.XAUnknown; long valueData = 0; for (int i = 0; xamlToRtfError == XamlToRtfError.None && i < nLen; i++) { xamlToRtfError = attributes.GetName(i, ref uri, ref newLocalName, ref newQName); if (xamlToRtfError == XamlToRtfError.None) { xamlToRtfError = attributes.GetValue(i, ref valueString); if (xamlToRtfError == XamlToRtfError.None && XamlParserHelper.ConvertToAttribute(converterState, newLocalName, ref attribute)) { switch (attribute) { case XamlAttribute.XAUnknown: break; case XamlAttribute.XAFontWeight: if (string.Compare(valueString, "Normal", StringComparison.OrdinalIgnoreCase) == 0) { formatState.Bold = false; } else if (string.Compare(valueString, "Bold", StringComparison.OrdinalIgnoreCase) == 0) { formatState.Bold = true; } break; case XamlAttribute.XAFontSize: double fs = 0f; if (XamlParserHelper.ConvertToFontSize(converterState, valueString, ref fs)) { formatState.FontSize = (long)Math.Round(fs); } break; case XamlAttribute.XAFontStyle: if (string.Compare(valueString, "Italic", StringComparison.OrdinalIgnoreCase) == 0) { formatState.Italic = true; } break; case XamlAttribute.XAFontFamily: if (XamlParserHelper.ConvertToFont(converterState, valueString, ref valueData)) { formatState.Font = valueData; } break; case XamlAttribute.XAFontStretch: if (XamlParserHelper.ConvertToFontStretch(converterState, valueString, ref valueData)) { formatState.Expand = valueData; } break; case XamlAttribute.XABackground: if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData)) { if (documentNode.IsInline) { formatState.CB = valueData; } else { formatState.CBPara = valueData; } } break; case XamlAttribute.XAForeground: if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData)) { formatState.CF = valueData; } break; case XamlAttribute.XAFlowDirection: DirState dirState = DirState.DirDefault; if (XamlParserHelper.ConvertToDir(converterState, valueString, ref dirState)) { if (documentNode.IsInline) { formatState.DirChar = dirState; } else if (documentNode.Type == DocumentNodeType.dnTable) { formatState.RowFormat.Dir = dirState; } else { formatState.DirPara = dirState; // Set the default inline flow direction as the paragraph's flow direction formatState.DirChar = dirState; } if (documentNode.Type == DocumentNodeType.dnList) { // Reset the left/right margin for List as the default value(720) // on RTL flow direction. Actually LI is set as 720 as the default // CreateDocumentNode(). if (formatState.DirPara == DirState.DirRTL) { formatState.LI = 0; formatState.RI = 720; } } } break; case XamlAttribute.XATextDecorations: { ULState ulState = ULState.ULNormal; StrikeState strikeState = StrikeState.StrikeNormal; if (XamlParserHelper.ConvertToDecoration(converterState, valueString, ref ulState, ref strikeState)) { if (ulState != ULState.ULNone) { formatState.UL = ulState; } if (strikeState != StrikeState.StrikeNone) { formatState.Strike = strikeState; } } } break; case XamlAttribute.XALocation: { ULState ulState = ULState.ULNormal; StrikeState strikeState = StrikeState.StrikeNormal; if (XamlParserHelper.ConvertToDecoration(converterState, valueString, ref ulState, ref strikeState)) { if (ulState != ULState.ULNone) { formatState.UL = ulState; } if (strikeState != StrikeState.StrikeNone) { formatState.Strike = strikeState; } } } break; case XamlAttribute.XARowSpan: { int nRowSpan = 0; if (Converters.StringToInt(valueString, ref nRowSpan)) { if (documentNode.Type == DocumentNodeType.dnCell) { documentNode.RowSpan = nRowSpan; } } } break; case XamlAttribute.XAColumnSpan: { int nColSpan = 0; if (Converters.StringToInt(valueString, ref nColSpan)) { if (documentNode.Type == DocumentNodeType.dnCell) { documentNode.ColSpan = nColSpan; } } } break; case XamlAttribute.XACellSpacing: { double d = 0f; if (Converters.StringToDouble(valueString, ref d)) { if (documentNode.Type == DocumentNodeType.dnTable) { formatState.RowFormat.Trgaph = Converters.PxToTwipRounded(d); } } } break; case XamlAttribute.XANavigateUri: if (xamlTag == XamlTag.XTHyperlink && valueString.Length > 0) { StringBuilder sb = new StringBuilder(); XamlParserHelper.AppendRTFText(sb, valueString, 0); documentNode.NavigateUri = sb.ToString(); } break; case XamlAttribute.XAWidth: if (xamlTag == XamlTag.XTTableColumn) { double d = 0f; if (Converters.StringToDouble(valueString, ref d)) { int nTableAt = dna.FindPending(DocumentNodeType.dnTable); if (nTableAt >= 0) { DocumentNode dnTable = dna.EntryAt(nTableAt); RowFormat rf = dnTable.FormatState.RowFormat; CellFormat cf = rf.NextCellFormat(); cf.Width.Type = WidthType.WidthTwips; cf.Width.Value = Converters.PxToTwipRounded(d); } } } else if (xamlTag == XamlTag.XTImage) { double d = 0f; Converters.StringToDouble(valueString, ref d); documentNode.FormatState.ImageWidth = d; } break; case XamlAttribute.XAHeight: if (xamlTag == XamlTag.XTImage) { double d = 0f; Converters.StringToDouble(valueString, ref d); documentNode.FormatState.ImageHeight = d; } break; case XamlAttribute.XASource: if (xamlTag == XamlTag.XTImage) { documentNode.FormatState.ImageSource = valueString; } break; case XamlAttribute.XAUriSource: if (xamlTag == XamlTag.XTBitmapImage) { documentNode.FormatState.ImageSource = valueString; } break; case XamlAttribute.XAStretch: if (xamlTag == XamlTag.XTImage) { documentNode.FormatState.ImageStretch = valueString; } break; case XamlAttribute.XAStretchDirection: if (xamlTag == XamlTag.XTImage) { documentNode.FormatState.ImageStretchDirection = valueString; } break; case XamlAttribute.XATypographyVariants: RtfSuperSubscript ss = RtfSuperSubscript.None; if (XamlParserHelper.ConvertToSuperSub(converterState, valueString, ref ss)) { if (ss == RtfSuperSubscript.Super) { formatState.Super = true; } else if (ss == RtfSuperSubscript.Sub) { formatState.Sub = true; } else if (ss == RtfSuperSubscript.Normal) { formatState.Sub = false; formatState.Super = false; } } break; case XamlAttribute.XAMarkerStyle: MarkerStyle ms = MarkerStyle.MarkerBullet; if (XamlParserHelper.ConvertToMarkerStyle(converterState, valueString, ref ms)) { formatState.Marker = ms; } break; case XamlAttribute.XAStartIndex: int nStart = 0; if (XamlParserHelper.ConvertToStartIndex(converterState, valueString, ref nStart)) { formatState.StartIndex = nStart; } break; case XamlAttribute.XAMargin: { XamlThickness thickness = new XamlThickness(0f, 0f, 0f, 0f); if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref thickness)) { formatState.LI = Converters.PxToTwipRounded(thickness.Left); formatState.RI = Converters.PxToTwipRounded(thickness.Right); formatState.SB = Converters.PxToTwipRounded(thickness.Top); formatState.SA = Converters.PxToTwipRounded(thickness.Bottom); } } break; case XamlAttribute.XAPadding: { XamlThickness t = new XamlThickness(0f, 0f, 0f, 0f); if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref t)) { if (xamlTag == XamlTag.XTParagraph) { // RTF only supports a single border padding value. formatState.ParaBorder.Spacing = Converters.PxToTwipRounded(t.Left); } else { RowFormat rf = formatState.RowFormat; CellFormat cf = rf.RowCellFormat; cf.PaddingLeft = Converters.PxToTwipRounded(t.Left); cf.PaddingRight = Converters.PxToTwipRounded(t.Right); cf.PaddingTop = Converters.PxToTwipRounded(t.Top); cf.PaddingBottom = Converters.PxToTwipRounded(t.Bottom); } } } break; case XamlAttribute.XABorderThickness: { XamlThickness t = new XamlThickness(0f, 0f, 0f, 0f); if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref t)) { if (xamlTag == XamlTag.XTParagraph) { ParaBorder pf = formatState.ParaBorder; pf.BorderLeft.Type = BorderType.BorderSingle; pf.BorderLeft.Width = Converters.PxToTwipRounded(t.Left); pf.BorderRight.Type = BorderType.BorderSingle; pf.BorderRight.Width = Converters.PxToTwipRounded(t.Right); pf.BorderTop.Type = BorderType.BorderSingle; pf.BorderTop.Width = Converters.PxToTwipRounded(t.Top); pf.BorderBottom.Type = BorderType.BorderSingle; pf.BorderBottom.Width = Converters.PxToTwipRounded(t.Bottom); } else { RowFormat rf = formatState.RowFormat; CellFormat cf = rf.RowCellFormat; cf.BorderLeft.Type = BorderType.BorderSingle; cf.BorderLeft.Width = Converters.PxToTwipRounded(t.Left); cf.BorderRight.Type = BorderType.BorderSingle; cf.BorderRight.Width = Converters.PxToTwipRounded(t.Right); cf.BorderTop.Type = BorderType.BorderSingle; cf.BorderTop.Width = Converters.PxToTwipRounded(t.Top); cf.BorderBottom.Type = BorderType.BorderSingle; cf.BorderBottom.Width = Converters.PxToTwipRounded(t.Bottom); } } } break; case XamlAttribute.XABorderBrush: if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData)) { if (xamlTag == XamlTag.XTParagraph) { formatState.ParaBorder.CF = valueData; } else { RowFormat rf = formatState.RowFormat; CellFormat cf = rf.RowCellFormat; cf.BorderLeft.CF = valueData; cf.BorderRight.CF = valueData; cf.BorderTop.CF = valueData; cf.BorderBottom.CF = valueData; } } break; case XamlAttribute.XATextIndent: double ti = 0; if (XamlParserHelper.ConvertToTextIndent(converterState, valueString, ref ti)) { formatState.FI = Converters.PxToTwipRounded(ti); } break; case XamlAttribute.XALineHeight: double sl = 0; if (XamlParserHelper.ConvertToLineHeight(converterState, valueString, ref sl)) { formatState.SL = Converters.PxToTwipRounded(sl); formatState.SLMult = false; } break; case XamlAttribute.XALang: { try { CultureInfo ci = new CultureInfo(valueString); if (ci.LCID > 0) { // Extract LANGID from LCID formatState.Lang = (long)(ushort)ci.LCID; } } catch (System.ArgumentException) { // Just omit if this is not a legal language value } } break; case XamlAttribute.XATextAlignment: HAlign halign = HAlign.AlignDefault; if (XamlParserHelper.ConvertToHAlign(converterState, valueString, ref halign)) { formatState.HAlign = halign; } break; } } } } } return xamlToRtfError; }
// Helper for IXamlContentHandler.StartElement. private DocumentNode CreateDocumentNode(ConverterState converterState, DocumentNodeType documentNodeType, DocumentNode dnTop, XamlTag xamlTag) { DocumentNode documentNode = new DocumentNode(documentNodeType); if (dnTop != null) { documentNode.InheritFormatState(dnTop.FormatState); } // Handle implicit formatting properties. switch (xamlTag) { case XamlTag.XTBold: documentNode.FormatState.Bold = true; break; case XamlTag.XTHyperlink: { long lColor = 0; documentNode.FormatState.UL = ULState.ULNormal; if (XamlParserHelper.ConvertToColor(converterState, "#FF0000FF", ref lColor)) { documentNode.FormatState.CF = lColor; } } break; case XamlTag.XTItalic: documentNode.FormatState.Italic = true; break; case XamlTag.XTUnderline: documentNode.FormatState.UL = ULState.ULNormal; break; case XamlTag.XTList: documentNode.FormatState.Marker = MarkerStyle.MarkerBullet; documentNode.FormatState.StartIndex = 1; // Set the default left margin for a list. documentNode.FormatState.LI = 720; break; } return documentNode; }