diff --git a/Src/xWorks/LcmWordGenerator.cs b/Src/xWorks/LcmWordGenerator.cs index 9c4a236771..551d468709 100644 --- a/Src/xWorks/LcmWordGenerator.cs +++ b/Src/xWorks/LcmWordGenerator.cs @@ -428,15 +428,56 @@ public void Append(WP.Table table) } /// - /// Appends a new run inside the last paragraph of the doc fragment--creates a new paragraph if none exists or if forceNewParagraph is true. + /// Appends a new run inside the last paragraph of the doc fragment--creates a new paragraph if none + /// exists or if forceNewParagraph is true. /// The run will be added to the end of the paragraph. /// /// The run to append. /// Even if a paragraph exists, force the creation of a new paragraph. public void AppendToParagraph(IFragment fragToCopy, OpenXmlElement run, bool forceNewParagraph) { + WP.Paragraph lastPar = null; + + if (forceNewParagraph) + { + // When forcing a new paragraph use a 'continuation' style for the new paragraph. + // The continuation style is based on the style used in the last paragraph. + string style = null; + WP.Paragraph lastParagraph = DocBody.OfType().LastOrDefault(); + if (lastParagraph != null) + { + WP.ParagraphProperties paraProps = lastParagraph.OfType().FirstOrDefault(); + if (paraProps != null) + { + ParagraphStyleId styleId = paraProps.OfType().FirstOrDefault(); + if (styleId != null && styleId.Val != null && styleId.Val.Value != null) + { + if (styleId.Val.Value.EndsWith(WordStylesGenerator.EntryStyleContinue)) + { + style = styleId.Val.Value; + } + else + { + style = styleId.Val.Value + WordStylesGenerator.EntryStyleContinue; + } + } + } + } + + lastPar = GetNewParagraph(); + if (!string.IsNullOrEmpty(style)) + { + WP.ParagraphProperties paragraphProps = new WP.ParagraphProperties( + new ParagraphStyleId() { Val = style }); + lastPar.Append(paragraphProps); + } + } + else + { + lastPar = GetLastParagraph(); + } + // Deep clone the run b/c of its tree of properties and to maintain styles. - WP.Paragraph lastPar = forceNewParagraph ? GetNewParagraph() : GetLastParagraph(); lastPar.AppendChild(CloneRun(fragToCopy, run)); } @@ -1064,12 +1105,19 @@ public void EndTable(IFragmentWriter writer, ConfigurableDictionaryNode config) } public void StartEntry(IFragmentWriter writer, ConfigurableDictionaryNode config, string className, Guid entryGuid, int index, RecordClerk clerk) { - // Each entry starts a new paragraph, and any entry data added will be added within the same paragraph. + // Each entry starts a new paragraph, and any entry data added will usually be added within the same paragraph. + // The paragraph will end whenever a data type that cannot be in a paragraph is encounter (Tables or Pictures). + // A new 'continuation' paragraph will be started after the Table ot Picture if there is other data that still + // needs to be added to the entry. // Create a new paragraph for the entry. DocFragment wordDoc = ((WordFragmentWriter)writer).WordFragment; WP.Paragraph entryPar = wordDoc.GetNewParagraph(); WP.ParagraphProperties paragraphProps = new WP.ParagraphProperties(new ParagraphStyleId() {Val = config.Style}); entryPar.Append(paragraphProps); + + // Create the 'continuation' style for the entry. This style will be the same as the style for the entry with the only + // difference being that it does not contain the first line indenting (since it is a continuation of the same entry). + AddStyles(config, true); } public void AddEntryData(IFragmentWriter writer, List pieces) { @@ -1318,6 +1366,17 @@ public void AddGlobalStyles(DictionaryConfigurationModel model, ReadOnlyProperty //WordStylesGenerator.GenerateWordStyleForAudioWs(_styleSheet, cache); } public string AddStyles(ConfigurableDictionaryNode node) + { + return AddStyles(node, false); + } + + /// + /// Generates styles that are needed by this node and adds them to the dictionary. + /// + /// If true then generate the 'continuation' style for the node. + /// If false then generate the regular (non-continuation) styles for the node. + /// + public string AddStyles(ConfigurableDictionaryNode node, bool addEntryContinuationStyle) { // The css className isn't important for the Word export. // Styles should be stored in the dictionary based on their stylenames. @@ -1326,7 +1385,15 @@ public string AddStyles(ConfigurableDictionaryNode node) lock (_styleDictionary) { - var styleContent = WordStylesGenerator.CheckRangeOfStylesForEmpties(WordStylesGenerator.GenerateWordStylesFromConfigurationNode(node, className, _propertyTable)); + Styles styleContent = null; + if (addEntryContinuationStyle) + { + styleContent = WordStylesGenerator.CheckRangeOfStylesForEmpties(WordStylesGenerator.GenerateContinuationWordStyles(node, _propertyTable)); + } + else + { + styleContent = WordStylesGenerator.CheckRangeOfStylesForEmpties(WordStylesGenerator.GenerateWordStylesFromConfigurationNode(node, className, _propertyTable)); + } if (styleContent == null) return className; if (!styleContent.Any()) diff --git a/Src/xWorks/WordStylesGenerator.cs b/Src/xWorks/WordStylesGenerator.cs index 90ddcfb63e..7a43cccc85 100644 --- a/Src/xWorks/WordStylesGenerator.cs +++ b/Src/xWorks/WordStylesGenerator.cs @@ -32,6 +32,7 @@ public class WordStylesGenerator internal const string WritingSystemPrefix = "writingsystemprefix"; internal const string WritingSystemStyleName = "Writing System Abbreviation"; internal const string PictureAndCaptionTextframeStyle = "Image-Textframe-Style"; + internal const string EntryStyleContinue = "-Continue"; public static Style GenerateLetterHeaderStyle( ReadOnlyPropertyTable propertyTable, LcmStyleSheet mediatorStyleSheet) @@ -81,7 +82,7 @@ internal static Style GenerateWordStyleFromLcmStyleSheet( ConfigurableDictionaryNode node, ReadOnlyPropertyTable propertyTable) { return GenerateWordStyleFromLcmStyleSheet(styleName, wsId, node, propertyTable, - false); + false, true); } /// @@ -95,10 +96,11 @@ internal static Style GenerateWordStyleFromLcmStyleSheet( /// writing system id /// The configuration node to use for generating paragraph margin in context /// To retrieve styles + /// Indicates if the style returned should include FirstLineIndent. /// internal static Style GenerateWordStyleFromLcmStyleSheet( string styleName, int wsId, ConfigurableDictionaryNode node, - ReadOnlyPropertyTable propertyTable, bool calculateFirstSenseStyle) + ReadOnlyPropertyTable propertyTable, bool calculateFirstSenseStyle, bool allowFirstLineIndent) { var styleSheet = FontHeightAdjuster.StyleSheetFromPropertyTable(propertyTable); if (styleSheet == null || !styleSheet.Styles.Contains(styleName)) @@ -177,7 +179,10 @@ internal static Style GenerateWordStyleFromLcmStyleSheet( hangingIndent = firstLineIndentValue; } - parProps.Append(new Indentation() { FirstLine = firstLineIndentValue.ToString() }); + if (allowFirstLineIndent) + { + parProps.Append(new Indentation() { FirstLine = firstLineIndentValue.ToString() }); + } } if (exportStyleInfo.HasKeepWithNext) @@ -576,6 +581,25 @@ private static Styles GenerateWordStylesForWritingSystemPrefix(ConfigurableDicti return styleRules; } + /// + /// Create the 'continuation' style for the entry, which is needed when an entry contains multiple paragraphs. This + /// style will be used for all but the first paragraph. It is the same as the style for the first paragraph except + /// that it does not contain the first line indenting. + /// + /// Returns the continuation style. + internal static Styles GenerateContinuationWordStyles( + ConfigurableDictionaryNode node, ReadOnlyPropertyTable propertyTable) + { + Style contStyle = GenerateWordStyleFromLcmStyleSheet(node.Style, DefaultStyle, node, + propertyTable, false, false); + contStyle.StyleName.Val = node.Style + EntryStyleContinue; + contStyle.StyleId = node.Style + EntryStyleContinue; + + var retStyles = new Styles(); + retStyles.AppendChild(contStyle.CloneNode(true)); + return retStyles; + } + /// /// Builds the word styles for font info properties using the writing system overrides ///