/// <summary> /// Gets style for PrintableStoryImageControl that will display images in the printed document /// </summary> protected virtual Style GetImageControlStyle(FlowDocumentStyleProvider styleProvider) { if (styleProvider != null) { return(styleProvider.ArticleImagePrintStyle); } return(null); }
protected virtual Style GetSectionTitleParagraphStyle(FlowDocumentStyleProvider styleProvider) { if (styleProvider != null && styleProvider is MsdnFlowDocumentStyleProvider) { return(((MsdnFlowDocumentStyleProvider)styleProvider).ArticleSectionTitleParagraphStyle); } return(null); }
/// <summary> /// Gets style for paragraph containing image controls /// </summary> protected virtual Style GetImageContainerStyle(FlowDocumentStyleProvider styleProvider) { if (styleProvider != null) { return(styleProvider.ArticleFigureContainerParagraphStyle); } return(null); }
protected virtual Style GetArticleCodeStyle(FlowDocumentStyleProvider styleProvider) { if (styleProvider != null && styleProvider is MsdnFlowDocumentStyleProvider) { return(((MsdnFlowDocumentStyleProvider)styleProvider).ArticleCodeStyle); } return(null); }
/// <summary> /// Override to get FlowDocumentStyle that gets style for print documents /// </summary> protected override Style GetFlowDocumentStyle(FlowDocumentStyleProvider styleProvider) { Style style = null; if (styleProvider != null) { style = styleProvider.ArticlePrintDocumentStyle; } if (style == null) { // No available style for print documents. Default to value returned by base style = base.GetFlowDocumentStyle(styleProvider); } return(style); }
/// <summary> /// Registers custom converters used by the application, sets up the FlowDocumentStyleProvider, etc. /// </summary> private void RegisterConverters() { // Set application's FlowDocumentStyleProvider as the source for flow document styling in the converter manager FlowDocumentStyleProvider styleProvider = Application.Current.TryFindResource("StoryFlowDocumentStyleProvider") as FlowDocumentStyleProvider; if (styleProvider != null) { ServiceProvider.ConverterManager.FlowDocumentStyleProvider = styleProvider; } MsdnEmailConverter emailConverter = new MsdnEmailConverter(); ServiceProvider.ConverterManager.EmailConverter = emailConverter; ServiceProvider.ConverterManager.UnRegister(typeof(Story), typeof(FlowDocument)); ServiceProvider.ConverterManager.Register(typeof(Story), typeof(FlowDocument), new MsdnStoryToFlowDocumentConverter()); }
/// <summary> /// ConvertAsync - produces formatted PrintableStoryFlowDocument and starts off async fetches for images sources of images inserted in /// the document /// </summary> public virtual void ConvertAsync(XPathDocument document, Story story, FlowDocumentStyleProvider styleProvider, object userState) { if (document == null) { throw new ArgumentNullException("document"); } XPathNavigator navigator = document.CreateNavigator(); XPathNavigator msdn = XmlHelper.GetChildNavigator(navigator, "content"); Story = story; // Get web figures for links pointing to code in browser, so these will work in a printed XPS document. // Images that open the viewer window cannot work in this context GetWebFigures(msdn, story); GetFlowDocumentFromNavigatorAsync(msdn, story, styleProvider, userState); }
protected void AddWebFigureLinkToBody(FlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider) { MsdnStoryImageHyperlink hyperlink = GetLinkToWebFigures(story, navigator, styleProvider); if (hyperlink != null) { Paragraph webFigureDownloadPara = new Paragraph(); ApplyStyle(webFigureDownloadPara, GetBodyTextParagraphStyle(styleProvider, 0)); webFigureDownloadPara.Inlines.Add(hyperlink); flowDocument.Blocks.Add(webFigureDownloadPara); } }
/// <summary> /// Creates a paragraph with a PrintableStoryImageControl to display images, and adds the control to the list of pending image requests /// </summary> protected virtual Paragraph CreateImageParagraph(Story story, ImageReference imageReference, ImageData imageData, FlowDocumentStyleProvider styleProvider) { PrintableStoryImageControl imageControl = new PrintableStoryImageControl(); imageControl.ImageReference = imageReference; imageControl.ImageData = imageData; imageControl.Story = story; MsdnStoryToFlowDocumentConverter.ApplyStyle(imageControl, GetImageControlStyle(styleProvider)); // Add the image control to the list of pending image request states if (_pendingImageRequestStates == null) { _pendingImageRequestStates = new List <PrintableStoryImageControl>(); } _pendingImageRequestStates.Add(imageControl); HeightAligner heightAligner = CreateHeightAligner(imageControl, WhitespaceDistribution.Split, styleProvider); Figure imageFigure = new Figure(new BlockUIContainer(heightAligner)); // Image figure may not be styled since we need to set its content and anchoring if (imageData.Width < 600) { imageFigure.Width = new FigureLength(1, FigureUnitType.Column); imageFigure.VerticalAnchor = FigureVerticalAnchor.ContentBottom; imageFigure.HorizontalAnchor = FigureHorizontalAnchor.ColumnCenter; } else { imageFigure.Width = new FigureLength(2, FigureUnitType.Column); imageFigure.VerticalAnchor = FigureVerticalAnchor.ContentBottom; imageFigure.HorizontalAnchor = FigureHorizontalAnchor.ContentLeft; } Paragraph imageParagraph = new Paragraph(imageFigure); MsdnStoryToFlowDocumentConverter.ApplyStyle(imageParagraph, GetImageContainerStyle(styleProvider)); return(imageParagraph); }
/// <summary> /// Creates a an MsdnStoryImageHyperlink element with a link to the image Uri/ImageReference /// </summary> protected MsdnStoryImageHyperlink CreateImageHyperlink(XPathNavigator navigator, TextPointer textPointer, FlowDocumentStyleProvider styleProvider) { MsdnStoryImageHyperlink hyperlink = null; if (navigator != null) { // If it's a figure containing code/ javascript, it will be referenced using the "ref" attribute Run run = new Run(XmlHelper.GetNavigatorText(navigator)); string webFigureRef = navigator.GetAttribute("ref", String.Empty); if (!String.IsNullOrEmpty(webFigureRef) && _webFigureStore.ContainsKey(webFigureRef)) { // 'ref' attribute found, try to match it with a web figure Uri Uri uri = _webFigureStore[webFigureRef]; hyperlink = new MsdnStoryImageHyperlink(uri, Story, run, textPointer); hyperlink.ToolTip = "View Code In Browser"; } else { // No attribute matched. Try to match figure text to an image caption from an Image element in the doc string text = XmlHelper.GetNavigatorText(navigator); if (!String.IsNullOrEmpty(text) && _imageReferenceFigureStore.ContainsKey(text)) { ImageReference imageReference = _imageReferenceFigureStore[text]; hyperlink = new MsdnStoryImageHyperlink(imageReference, Story, run, textPointer); hyperlink.ToolTip = "View Image"; } } if (hyperlink != null) { ApplyStyle(hyperlink, GetHyperlinkStyle(styleProvider)); hyperlink.RequestNavigate += ((MsdnViewManager)ServiceProvider.ViewManager).OnImageHyperlinkRequestNavigate; } } return(hyperlink); }
/// <summary> /// Override for CreateStyledInline checks for Fig tags to create special hyperlinks for images /// </summary> /// <param name="navigator"></param> /// <param name="textPointer"></param> /// <param name="styleProvider"></param> /// <returns></returns> protected override Inline CreateStyledInline(XPathNavigator navigator, TextPointer textPointer, FlowDocumentStyleProvider styleProvider) { Inline inline = null; if (textPointer != null) { if (navigator.NodeType == XPathNodeType.Element) { switch (navigator.Name.ToLowerInvariant()) { case "fig": inline = CreateImageHyperlink(navigator, textPointer, styleProvider); break; default: break; } } } if (inline == null) { inline = base.CreateStyledInline(navigator, textPointer, styleProvider); } return(inline); }
/// <summary> /// Creates title for sections /// </summary> protected virtual Paragraph CreateSectionTitleParagraph(XPathNavigator titleNavigator, Story story, FlowDocumentStyleProvider styleProvider) { Paragraph paragraph = new Paragraph(new Run()); // Navigate paragraph using a duplicate navigator. Step inside paragraph's first child before beginning navigation XPathNavigator parsingNavigator = titleNavigator.CreateNavigator(); if (parsingNavigator.NodeType == XPathNodeType.Element && parsingNavigator.Name.ToLower(CultureInfo.InvariantCulture) == "title" && parsingNavigator.MoveToFirstChild()) { ParseContent(parsingNavigator.CreateNavigator(), paragraph.ContentStart, styleProvider); } MsdnStoryToFlowDocumentConverter.ApplyStyle(paragraph, GetSectionTitleParagraphStyle(styleProvider)); return(paragraph); }
/// <summary> /// Creates a body text paragraph from body navigator. Paragraph number is passed in in case different styles /// are desired for the first paragraph, etc. /// </summary> protected override Paragraph CreateBodyTextParagraph(XPathNavigator paragraphNavigator, Story story, FlowDocumentStyleProvider styleProvider, int paragraphNumber) { Paragraph paragraph = new Paragraph(new Run()); // Navigate paragraph using a duplicate navigator. Step inside paragraph's first child before beginning navigation XPathNavigator parsingNavigator = paragraphNavigator.CreateNavigator(); if (parsingNavigator.NodeType == XPathNodeType.Element && parsingNavigator.Name.ToLower(CultureInfo.InvariantCulture) == "para" && parsingNavigator.MoveToFirstChild()) { ParseContent(parsingNavigator.CreateNavigator(), paragraph.ContentStart, styleProvider); } ApplyStyle(paragraph, GetBodyTextParagraphStyle(styleProvider, paragraphNumber)); return(paragraph); }
protected virtual void AddCopyrightNoticeToBody(FlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider) { MsdnFlowDocumentStyleProvider msdnStyleProvider = styleProvider as MsdnFlowDocumentStyleProvider; CreateCopyrightNoticeParagraph(flowDocument, msdnStyleProvider); }
protected virtual void AddAuthorAndBioToBody(FlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider) { XPathNavigator headerNavigator = GetHeaderNavigator(navigator); MsdnFlowDocumentStyleProvider msdnStyleProvider = styleProvider as MsdnFlowDocumentStyleProvider; CreateBioTextParagraph(flowDocument, headerNavigator, story, msdnStyleProvider); }
protected override void CreateBody(FlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider) { XPathNavigator bodyNavigator = GetBodyNavigator(navigator); XPathNodeIterator bodyParagraphIterator = GetBodyParagraphIterator(bodyNavigator); List <ImageData> storyImageData = null; List <ImageReference> storyImages = GetStoryImages(story, out storyImageData); int imageCounter = 0; int imageSpacing = CalculateImageSpacing(bodyParagraphIterator, storyImages); if (bodyParagraphIterator != null) { // Iterate through sections while (bodyParagraphIterator.MoveNext()) { if (bodyParagraphIterator.CurrentPosition == 1 && imageSpacing > 0) { // Always put an image first if there is one if (imageCounter < storyImages.Count) { Paragraph imageParagraph = CreateImageParagraph(story, storyImages[imageCounter], storyImageData[imageCounter], styleProvider); imageCounter++; flowDocument.Blocks.Add(imageParagraph); } } else if (bodyParagraphIterator.CurrentPosition > 0 && imageSpacing > 0 && (bodyParagraphIterator.CurrentPosition % imageSpacing == 0)) { if (imageCounter < storyImages.Count) { Paragraph imageParagraph = CreateImageParagraph(story, storyImages[imageCounter], storyImageData[imageCounter], styleProvider); imageCounter++; flowDocument.Blocks.Add(imageParagraph); } } // Get title of section XPathNavigator titleNavigator = GetSectionTitleNavigator(bodyParagraphIterator.Current); if (titleNavigator != null) { Paragraph paragraph = CreateSectionTitleParagraph(titleNavigator, story, styleProvider); flowDocument.Blocks.Add(paragraph); } XPathNodeIterator innerBodyParagraphIterator = GetInnerBodyParagraphIterator(bodyParagraphIterator.Current); if (innerBodyParagraphIterator != null) { while (innerBodyParagraphIterator.MoveNext()) { Paragraph paragraph = null; XPathNavigator codeNavigator = innerBodyParagraphIterator.Current.SelectSingleNode("Code"); if (codeNavigator == null) { paragraph = CreateBodyTextParagraph(innerBodyParagraphIterator.Current, story, styleProvider, innerBodyParagraphIterator.CurrentPosition); } else { paragraph = CreateCodeParagraph(codeNavigator, story, styleProvider); } flowDocument.Blocks.Add(paragraph); } } } } AddAuthorAndBioToBody(flowDocument, navigator, story, styleProvider); AddCopyrightNoticeToBody(flowDocument, navigator, story, styleProvider); }
/// <summary> /// Creates headline and byline paragraphs /// </summary> protected override void CreateHeadline(FlowDocument flowDocument, XPathNavigator nitfNavigator, Story story, FlowDocumentStyleProvider styleProvider) { XPathNavigator headerNavigator = GetHeaderNavigator(nitfNavigator); MsdnFlowDocumentStyleProvider msdnStyleProvider = styleProvider as MsdnFlowDocumentStyleProvider; CreateHeadlineParagraph(flowDocument, headerNavigator, story, msdnStyleProvider); CreateAuthorIssueParagraph(flowDocument, headerNavigator, nitfNavigator, story, msdnStyleProvider); CreateLinkToSampleCodeParagraph(flowDocument, headerNavigator, story, msdnStyleProvider); //CreateBylineDateParagraph(flowDocument, headerNavigator, story, styleProvider); }
/// <summary> /// CreateBodyAsync calls CreateBody to produce the FlowDocument, then begins async download of image sources. /// If download is pending, or if there are no image sources in the document, it raises completed event /// </summary> protected virtual void CreateBodyAsync(PrintableStoryFlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider, object userState) { if (!IsImageDownloadPending) { CreateBody(flowDocument, navigator, story, styleProvider); // Check if image source fetches are needed if (_pendingImageRequestStates != null && _pendingImageRequestStates.Count > 0) { // Request image sources. Store the FlowDocument as our user state and exit. Completed event is raised when image fetches complete _targetDocument = flowDocument; _dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(GetImageSources), userState); return; } } // Fallback: either there are no image sources to fetch, or downloads are pending. Raise completed event ConversionCompletedEventArgs args = new ConversionCompletedEventArgs(userState, flowDocument); _dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(RaiseConversionCompleted), args); }
/// <summary> /// Creates formatted FlowDocument /// </summary> protected virtual void GetFlowDocumentFromNavigatorAsync(XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider, object userState) { PrintableStoryFlowDocument flowDocument = new PrintableStoryFlowDocument(); MsdnStoryToFlowDocumentConverter.ApplyStyle(flowDocument, GetFlowDocumentStyle(styleProvider)); // Headline does not require async fetches, so the base class method can be used CreateHeadline(flowDocument, navigator, story, styleProvider); CreateBodyAsync(flowDocument, navigator, story, styleProvider, userState); }
/// <summary> /// Creates document body /// </summary> protected override void CreateBody(FlowDocument flowDocument, XPathNavigator navigator, Story story, FlowDocumentStyleProvider styleProvider) { XPathNavigator bodyNavigator = GetBodyNavigator(navigator); XPathNodeIterator bodyParagraphIterator = GetBodyParagraphIterator(bodyNavigator); if (bodyParagraphIterator != null) { // Iterate through sections while (bodyParagraphIterator.MoveNext()) { // Get title of section XPathNavigator titleNavigator = GetSectionTitleNavigator(bodyParagraphIterator.Current); if (titleNavigator != null) { Paragraph paragraph = CreateSectionTitleParagraph(titleNavigator, story, styleProvider); flowDocument.Blocks.Add(paragraph); } XPathNodeIterator innerBodyParagraphIterator = GetInnerBodyParagraphIterator(bodyParagraphIterator.Current); if (innerBodyParagraphIterator != null) { while (innerBodyParagraphIterator.MoveNext()) { Paragraph paragraph = null; XPathNavigator codeNavigator = innerBodyParagraphIterator.Current.SelectSingleNode("Code"); if (codeNavigator == null) { paragraph = CreateBodyTextParagraph(innerBodyParagraphIterator.Current, story, styleProvider, innerBodyParagraphIterator.CurrentPosition); } else { paragraph = CreateCodeParagraph(codeNavigator, story, styleProvider); } flowDocument.Blocks.Add(paragraph); } } } } AddWebFigureLinkToBody(flowDocument, navigator, story, styleProvider); AddAuthorAndBioToBody(flowDocument, navigator, story, styleProvider); AddCopyrightNoticeToBody(flowDocument, navigator, story, styleProvider); }
protected MsdnStoryImageHyperlink GetLinkToWebFigures(Story story, XPathNavigator navigator, FlowDocumentStyleProvider styleProvider) { MsdnStoryImageHyperlink hyperlink = null; XPathNavigator figuresNavigator = navigator.SelectSingleNode("Figures"); if (figuresNavigator != null) { // Figures exist, add link hyperlink = new MsdnStoryImageHyperlink(GetMagazineArticleWebFigureUri(story), story); hyperlink.Inlines.Add(new Run("See all code figures for this article")); hyperlink.ToolTip = "View Code Figures In Browser"; hyperlink.RequestNavigate += ((MsdnViewManager)ServiceProvider.ViewManager).OnImageHyperlinkRequestNavigate; } return(hyperlink); }