Skip to content

Commit

Permalink
Implement the ability to set the spacing before and after a paragraph
Browse files Browse the repository at this point in the history
  • Loading branch information
y0ung3r committed Apr 25, 2024
1 parent 6c7253b commit 4908fd4
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
using OfficeFlow.Word.Core.Elements.Paragraphs.Enums;
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs.Enums;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;
using OfficeFlow.Word.Core.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs;

public sealed record ParagraphFormat : IVisitable
public sealed class ParagraphFormat : IVisitable
{
public static ParagraphFormat Default
=> new()
{
HorizontalAlignment = HorizontalAlignment.Left
};
=> new();

public HorizontalAlignment HorizontalAlignment { get; set; }
public HorizontalAlignment HorizontalAlignment { get; set; }
= HorizontalAlignment.Left;

public IParagraphSpacing SpacingBefore { get; set; }
= ParagraphSpacing.Exactly<Points>(0);

public IParagraphSpacing SpacingAfter { get; set; }
= ParagraphSpacing.Exactly<Points>(8.0);

/// <inheritdoc />
public void Accept(IWordVisitor visitor)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;

public sealed class AtLeastSpacing : ILineSpacing, IEquatable<AtLeastSpacing>
{
public AbsoluteValue<Points> Value { get; }

internal AtLeastSpacing(AbsoluteValue<Points> value)
=> Value = value;

public bool Equals(AtLeastSpacing? other)
{
if (ReferenceEquals(null, other))
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

return Value.Equals(other.Value);
}

/// <inheritdoc />
public override bool Equals(object? other)
{
if (ReferenceEquals(null, other))
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

if (other.GetType() != GetType())
{
return false;
}

return Equals((AtLeastSpacing)other);
}

/// <inheritdoc />
public override int GetHashCode()
=> Value.GetHashCode();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;

public sealed class AutoSpacing : IParagraphSpacing, ILineSpacing
{
internal AutoSpacing()
{ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;

public sealed class ExactSpacing : IParagraphSpacing, ILineSpacing, IEquatable<ExactSpacing>
{
public AbsoluteValue<Points> Value { get; }

internal ExactSpacing(AbsoluteValue<Points> value)
=> Value = value;

public bool Equals(ExactSpacing? other)
{
if (ReferenceEquals(null, other))
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

return Value.Equals(other.Value);
}

/// <inheritdoc />
public override bool Equals(object? other)
{
if (ReferenceEquals(null, other))
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

if (other.GetType() != GetType())
{
return false;
}

return Equals((ExactSpacing)other);
}

/// <inheritdoc />
public override int GetHashCode()
=> Value.GetHashCode();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

public interface ILineSpacing
{ }
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

public interface IParagraphSpacing
{ }
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;

public static class LineSpacing
{
public static ILineSpacing Exactly<TUnits>(AbsoluteValue<TUnits> value)
where TUnits : AbsoluteUnits, new()
=> new ExactSpacing(
value.To<Points>());

public static ILineSpacing Exactly<TUnits>(double value)
where TUnits : AbsoluteUnits, new()
=> Exactly(
AbsoluteValue<TUnits>.From(value));

public static ILineSpacing AtLeast<TUnits>(AbsoluteValue<TUnits> value)
where TUnits : AbsoluteUnits, new()
=> new AtLeastSpacing(
value.To<Points>());

public static ILineSpacing AtLeast<TUnits>(double value)
where TUnits : AbsoluteUnits, new()
=> AtLeast(
AbsoluteValue<TUnits>.From(value));

public static readonly ILineSpacing Auto
= new AutoSpacing();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing.Interfaces;

namespace OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;

public static class ParagraphSpacing
{
public static IParagraphSpacing Exactly<TUnits>(AbsoluteValue<TUnits> value)
where TUnits : AbsoluteUnits, new()
=> new ExactSpacing(
value.To<Points>());

public static IParagraphSpacing Exactly<TUnits>(double value)
where TUnits : AbsoluteUnits, new()
=> Exactly(
AbsoluteValue<TUnits>.From(value));

public static readonly IParagraphSpacing Auto
= new AutoSpacing();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Xml.Linq;
using FluentAssertions;
using OfficeFlow.MeasureUnits.Absolute;
using OfficeFlow.Word.Core.Elements.Paragraphs;
using OfficeFlow.Word.Core.Elements.Paragraphs.Enums;
using OfficeFlow.Word.Core.Elements.Paragraphs.Spacing;
using Xunit;

namespace OfficeFlow.Word.OpenXml.Tests.OpenXmlElementReaderTests;
Expand Down Expand Up @@ -36,6 +38,129 @@ public void Should_read_horizontal_alignment_properly(string actualValue, Horizo
.Be(expectedValue);
}

[Fact]
public void Should_read_paragraph_spacing_properly()
{
// Arrange
var xml = new XElement(OpenXmlNamespaces.Word + "pPr",
new XElement(OpenXmlNamespaces.Word + "spacing",
new XAttribute(OpenXmlNamespaces.Word + "before", "240"),
new XAttribute(OpenXmlNamespaces.Word + "beforeAutospacing", "true"),
new XAttribute(OpenXmlNamespaces.Word + "after", "240"),
new XAttribute(OpenXmlNamespaces.Word + "afterAutospacing", "false")));

var paragraphFormat = new ParagraphFormat();
var sut = new OpenXmlElementReader(xml);

// Act
sut.Visit(paragraphFormat);

// Assert
paragraphFormat
.SpacingBefore
.Should()
.BeOfType<AutoSpacing>();

paragraphFormat
.SpacingAfter
.Should()
.BeOfType<ExactSpacing>()
.And
.Be(ParagraphSpacing.Exactly<Points>(12.0));
}

[Theory]
[InlineData("1")]
[InlineData("true")]
public void Spacing_after_should_be_calculated_automatically(string value)
{
// Arrange
var xml = new XElement(OpenXmlNamespaces.Word + "pPr",
new XElement(OpenXmlNamespaces.Word + "spacing",
new XAttribute(OpenXmlNamespaces.Word + "afterAutospacing", value)));

var paragraphFormat = new ParagraphFormat();
var sut = new OpenXmlElementReader(xml);

// Act
sut.Visit(paragraphFormat);

// Assert
paragraphFormat
.SpacingAfter
.Should()
.BeOfType<AutoSpacing>();
}

[Theory]
[InlineData("1")]
[InlineData("true")]
public void Spacing_before_should_be_calculated_automatically(string value)
{
// Arrange
var xml = new XElement(OpenXmlNamespaces.Word + "pPr",
new XElement(OpenXmlNamespaces.Word + "spacing",
new XAttribute(OpenXmlNamespaces.Word + "beforeAutospacing", value)));

var paragraphFormat = new ParagraphFormat();
var sut = new OpenXmlElementReader(xml);

// Act
sut.Visit(paragraphFormat);

// Assert
paragraphFormat
.SpacingBefore
.Should()
.BeOfType<AutoSpacing>();
}

[Fact]
public void Should_read_exact_value_of_spacing_after_properly()
{
// Arrange
var xml = new XElement(OpenXmlNamespaces.Word + "pPr",
new XElement(OpenXmlNamespaces.Word + "spacing",
new XAttribute(OpenXmlNamespaces.Word + "after", "240")));

var paragraphFormat = new ParagraphFormat();
var sut = new OpenXmlElementReader(xml);

// Act
sut.Visit(paragraphFormat);

// Assert
paragraphFormat
.SpacingAfter
.Should()
.BeOfType<ExactSpacing>()
.And
.Be(ParagraphSpacing.Exactly<Points>(12.0));
}

[Fact]
public void Should_read_exact_value_of_spacing_before_properly()
{
// Arrange
var xml = new XElement(OpenXmlNamespaces.Word + "pPr",
new XElement(OpenXmlNamespaces.Word + "spacing",
new XAttribute(OpenXmlNamespaces.Word + "before", "240")));

var paragraphFormat = new ParagraphFormat();
var sut = new OpenXmlElementReader(xml);

// Act
sut.Visit(paragraphFormat);

// Assert
paragraphFormat
.SpacingBefore
.Should()
.BeOfType<ExactSpacing>()
.And
.Be(ParagraphSpacing.Exactly<Points>(12.0));
}

[Fact]
public void Should_read_empty_paragraph_format_properly()
{
Expand All @@ -53,5 +178,15 @@ public void Should_read_empty_paragraph_format_properly()
.HorizontalAlignment
.Should()
.Be(ParagraphFormat.Default.HorizontalAlignment);

paragraphFormat
.SpacingBefore
.Should()
.Be(ParagraphFormat.Default.SpacingBefore);

paragraphFormat
.SpacingAfter
.Should()
.Be(ParagraphFormat.Default.SpacingAfter);
}
}
Loading

0 comments on commit 4908fd4

Please sign in to comment.