Skip to content

Commit

Permalink
LT-21761: Fix indenting for the first line after a Table
Browse files Browse the repository at this point in the history
The first line of an entry typically uses FirstLineIndent to
indented to the left. When we have multiple paragraphs for an
entry (because the entry contains Tables or Pictures)
then we do not want the line following the Table or Picture to
also be indented to the left. We now create a ‘continuation’
style for paragraphs following a table or picture.  It is the
same as the original style except it does not use
FirstLineIndent.

Change-Id: I67e282e4a02f1ff9145dfb198c4432823d156413
  • Loading branch information
mark-sil committed May 1, 2024
1 parent c351ca8 commit 6e46cb0
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 7 deletions.
75 changes: 71 additions & 4 deletions Src/xWorks/LcmWordGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,15 +428,56 @@ public void Append(WP.Table table)
}

/// <summary>
/// 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.
/// </summary>
/// <param name="run">The run to append.</param>
/// <param name="forceNewParagraph">Even if a paragraph exists, force the creation of a new paragraph.</param>
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<WP.Paragraph>().LastOrDefault();
if (lastParagraph != null)
{
WP.ParagraphProperties paraProps = lastParagraph.OfType<WP.ParagraphProperties>().FirstOrDefault();
if (paraProps != null)
{
ParagraphStyleId styleId = paraProps.OfType<WP.ParagraphStyleId>().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));
}

Expand Down Expand Up @@ -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<ConfiguredLcmGenerator.ConfigFragment> pieces)
{
Expand Down Expand Up @@ -1318,6 +1366,17 @@ public void AddGlobalStyles(DictionaryConfigurationModel model, ReadOnlyProperty
//WordStylesGenerator.GenerateWordStyleForAudioWs(_styleSheet, cache);
}
public string AddStyles(ConfigurableDictionaryNode node)
{
return AddStyles(node, false);
}

/// <summary>
/// Generates styles that are needed by this node and adds them to the dictionary.
/// </summary>
/// <param name="addEntryContinuationStyle">If true then generate the 'continuation' style for the node.
/// If false then generate the regular (non-continuation) styles for the node.</param>
/// <returns></returns>
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.
Expand All @@ -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())
Expand Down
30 changes: 27 additions & 3 deletions Src/xWorks/WordStylesGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -81,7 +82,7 @@ internal static Style GenerateWordStyleFromLcmStyleSheet(
ConfigurableDictionaryNode node, ReadOnlyPropertyTable propertyTable)
{
return GenerateWordStyleFromLcmStyleSheet(styleName, wsId, node, propertyTable,
false);
false, true);
}

/// <summary>
Expand All @@ -95,10 +96,11 @@ internal static Style GenerateWordStyleFromLcmStyleSheet(
/// <param name="wsId">writing system id</param>
/// <param name="node">The configuration node to use for generating paragraph margin in context</param>
/// <param name="propertyTable">To retrieve styles</param>
/// <param name="allowFirstLineIndent">Indicates if the style returned should include FirstLineIndent.</param>
/// <returns></returns>
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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -576,6 +581,25 @@ private static Styles GenerateWordStylesForWritingSystemPrefix(ConfigurableDicti
return styleRules;
}

/// <summary>
/// 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.
/// </summary>
/// <returns>Returns the continuation style.</returns>
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;
}

/// <summary>
/// Builds the word styles for font info properties using the writing system overrides
/// </summary>
Expand Down

0 comments on commit 6e46cb0

Please sign in to comment.