Skip to content

Commit

Permalink
Merge pull request ShapeCrawler#339 from ShapeCrawler/fill-shape
Browse files Browse the repository at this point in the history
Fix infinitive loop
  • Loading branch information
ashahabov authored Oct 4, 2022
2 parents 330e787 + 859c19d commit 41e31e8
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 61 deletions.
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions ShapeCrawler.Tests/ShapeCrawler.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@
<EmbeddedResource Include="Resource\018.pptx" />
<None Remove="Resource\autoshape\autoshape-case006_field.pptx" />
<EmbeddedResource Include="Resource\autoshape\autoshape-case006_field.pptx" />
<None Remove="Resource\autoshape\autoshape-case007.pptx" />
<EmbeddedResource Include="Resource\autoshape\autoshape-case007.pptx" />
<None Remove="Resource\autoshape\autoshape-case008_text-frame.pptx" />
<EmbeddedResource Include="Resource\autoshape\autoshape-case008_text-frame.pptx" />
</ItemGroup>

</Project>
57 changes: 40 additions & 17 deletions ShapeCrawler.Tests/TextFrameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public static TheoryData<TestElementQuery> TestCasesTextSetter
get
{
var testCases = new TheoryData<TestElementQuery>();

var case1 = new TestElementQuery
{
Presentation = SCPresentation.Open(GetTestStream("001.pptx")),
Expand Down Expand Up @@ -149,6 +149,14 @@ public static TheoryData<TestElementQuery> TestCasesTextSetter
ShapeName = "Subtitle 1",
};
testCases.Add(case4);

var case5 = new TestElementQuery
{
Presentation = SCPresentation.Open(GetTestStream("autoshape-case008_text-frame.pptx")),
SlideNumber = 1,
ShapeName = "AutoShape 1",
};
testCases.Add(case5);

return testCases;
}
Expand Down Expand Up @@ -510,33 +518,48 @@ public static IEnumerable<object[]> TestCasesParagraphsCount
}

[Fact]
public void ParagraphsAdd_AddsANewTextParagraphAtTheEndOfTheTextBoxAndReturnsAddedParagraph()
public void Paragraphs_Add_adds_new_text_paragraph_at_the_end_And_returns_added_paragraph()
{
// Arrange
const string TEST_TEXT = "ParagraphsAdd";
var mStream = new MemoryStream();
IPresentation presentation = SCPresentation.Open(Resources._001);
ITextFrame textBox = ((IAutoShape)presentation.Slides[0].Shapes.First(sp => sp.Id == 4)).TextFrame;
int originParagraphsCount = textBox.Paragraphs.Count;
var pres = SCPresentation.Open(Resources._001);
var textFrame = ((IAutoShape)pres.Slides[0].Shapes.First(sp => sp.Id == 4)).TextFrame;
int originParagraphsCount = textFrame.Paragraphs.Count;

// Act
IParagraph newParagraph = textBox.Paragraphs.Add();
newParagraph.Text = TEST_TEXT;
var addedPara = textFrame.Paragraphs.Add();
addedPara.Text = TEST_TEXT;

// Assert
var lastPara = textFrame.Paragraphs.Last();
lastPara.Text.Should().BeEquivalentTo(TEST_TEXT);
textFrame.Paragraphs.Should().HaveCountGreaterThan(originParagraphsCount);

pres.SaveAs(mStream);
pres = SCPresentation.Open(mStream);
textFrame = ((IAutoShape)pres.Slides[0].Shapes.First(sp => sp.Id == 4)).TextFrame;
textFrame.Paragraphs.Last().Text.Should().BeEquivalentTo(TEST_TEXT);
textFrame.Paragraphs.Should().HaveCountGreaterThan(originParagraphsCount);
}

[Fact]
public void Paragraphs_Add_adds_paragraph()
{
// Arrange
var pptxStream = GetTestStream("autoshape-case007.pptx");
var pres = SCPresentation.Open(pptxStream);
var paragraphs = pres.Slides[0].Shapes.GetByName<IAutoShape>("AutoShape 1").TextFrame.Paragraphs;

// Act
paragraphs.Add();

// Assert
textBox.Paragraphs.Last().Text.Should().BeEquivalentTo(TEST_TEXT);
textBox.Paragraphs.Should().HaveCountGreaterThan(originParagraphsCount);

presentation.SaveAs(mStream);
presentation = SCPresentation.Open(mStream);
textBox = ((IAutoShape)presentation.Slides[0].Shapes.First(sp => sp.Id == 4)).TextFrame;
textBox.Paragraphs.Last().Text.Should().BeEquivalentTo(TEST_TEXT);
textBox.Paragraphs.Should().HaveCountGreaterThan(originParagraphsCount);
paragraphs.Should().HaveCount(6);
}

[Fact]
public void
Paragraphs_Add_returns_a_new_added_paragraph_When_paragraph_has_been_added_after_text_box_content_changed()
public void Paragraphs_Add_adds_new_text_paragraph_at_the_end_And_returns_added_paragraph_When_it_has_been_added_after_text_frame_changed()
{
var pres = SCPresentation.Open(Properties.Resources._001);
var autoShape = (IAutoShape)pres.Slides[0].Shapes.First(sp => sp.Id == 3);
Expand Down
3 changes: 2 additions & 1 deletion ShapeCrawler/AutoShapes/SCFont.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using DocumentFormat.OpenXml;
using ShapeCrawler.Constants;
using ShapeCrawler.Exceptions;
using ShapeCrawler.Extensions;
using ShapeCrawler.Factories;
Expand Down Expand Up @@ -203,7 +204,7 @@ private int GetSize()
}
}

return FormatConstants.DefaultFontSize;
return SCConstants.DefaultFontSize;
}

private bool GetBoldFlag()
Expand Down
38 changes: 20 additions & 18 deletions ShapeCrawler/AutoShapes/SCParagraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,21 @@ public void AddPortion(string text)
}

var lastPortion = this.portions.Value.LastOrDefault() as SCPortion;
OpenXmlElement aTextParent;
OpenXmlElement aRun;
OpenXmlElement? lastARunOrABreak = null;
if (lastPortion == null)
{
var aRunBuilder = new ARunBuilder();
aTextParent = aRunBuilder.Build();
aRun = aRunBuilder.Build();
}
else
{
aTextParent = lastPortion.AText.Parent!;
aRun = lastPortion.AText.Parent!;
lastARunOrABreak = this.AParagraph.Last(p => p is A.Run or A.Break);
}

if (lastARunOrABreak is not A.Break && this.Text.EndsWith(Environment.NewLine, StringComparison.Ordinal))
{
AddBreak(ref lastARunOrABreak);
if (lastARunOrABreak is not A.Break && this.Text.EndsWith(Environment.NewLine, StringComparison.Ordinal))
{
AddBreak(ref lastARunOrABreak);
}
}

var textLines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
Expand All @@ -94,15 +93,15 @@ public void AddPortion(string text)
}
else
{
AddText(ref lastARunOrABreak, aTextParent, textLines[0], this.AParagraph);
AddText(ref lastARunOrABreak, aRun, textLines[0], this.AParagraph);
}

for (var i = 1; i < textLines.Length; i++)
{
AddBreak(ref lastARunOrABreak);
if (textLines[i] != string.Empty)
{
AddText(ref lastARunOrABreak, aTextParent, textLines[i], this.AParagraph);
AddText(ref lastARunOrABreak, aRun, textLines[i], this.AParagraph);
}
}

Expand Down Expand Up @@ -164,25 +163,28 @@ private string GetText()
return this.Portions.Select(portion => portion.Text).Aggregate((result, next) => result + next);
}

private void SetText(string newText)
private void SetText(string text)
{
this.ThrowIfRemoved();

// To set a paragraph text we use a single portion which is the first paragraph portion.
if (this.portions.Value.Count == 0)
{
this.AddPortion(" ");
}

// to set a paragraph text we use a single portion which is the first paragraph portion.
var removingPortions = this.Portions.Skip(1).ToList();

this.Portions.Remove(removingPortions);

var basePortion = (SCPortion)this.portions.Value.Single();

basePortion.Text = string.Empty;
if (newText.Contains(Environment.NewLine))
if (text.Contains(Environment.NewLine))
{
basePortion.Text = string.Empty;
this.AddPortion(newText);
this.AddPortion(text);
}
else
{
basePortion.Text = newText;
basePortion.Text = text;
}
}

Expand Down
1 change: 0 additions & 1 deletion ShapeCrawler/AutoShapes/SlideAutoShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ internal SlideAutoShape(P.Shape pShape, SCSlide slideInternal, SlideGroupShape g
private TextFrame? GetTextBox()
{
var pTextBody = this.PShapeTreesChild.GetFirstChild<P.TextBody>();
var canChangeText = this.Placeholder is null or not { Type: SCPlaceholderType.DateAndTime } and not { Type: SCPlaceholderType.SlideNumber };
return pTextBody == null ? null : new TextFrame(this, pTextBody);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace ShapeCrawler.Statics
namespace ShapeCrawler.Constants
{
/// <summary>
/// Contains library limitation..
/// Contains library limitation.
/// </summary>
internal static class Limitations
{
Expand Down
10 changes: 10 additions & 0 deletions ShapeCrawler/Constants/SCConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ShapeCrawler.Constants;

internal class SCConstants
{
internal const int MinReduceFontSize = 5;

internal const string CustomDataElementName = "ctd";

internal static int DefaultFontSize => 18; // https://bit.ly/37Tjjlo
}
1 change: 1 addition & 0 deletions ShapeCrawler/PowerPoint/SCPresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using DocumentFormat.OpenXml.Packaging;
using ShapeCrawler.Charts;
using ShapeCrawler.Collections;
using ShapeCrawler.Constants;
using ShapeCrawler.Exceptions;
using ShapeCrawler.Extensions;
using ShapeCrawler.Factories;
Expand Down
9 changes: 5 additions & 4 deletions ShapeCrawler/PowerPoint/SCSlide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using DocumentFormat.OpenXml.Presentation;
using ShapeCrawler.AutoShapes;
using ShapeCrawler.Collections;
using ShapeCrawler.Constants;
using ShapeCrawler.Exceptions;
using ShapeCrawler.Services;
using ShapeCrawler.Shapes;
Expand Down Expand Up @@ -226,9 +227,9 @@ private string GetCustomData()
using var customXmlStreamReader = new StreamReader(customXmlPartStream);
var raw = customXmlStreamReader.ReadToEnd();
#if NET6_0
return raw[ConstantStrings.CustomDataElementName.Length..];
return raw[SCConstants.CustomDataElementName.Length..];
#else
return raw.Substring(ConstantStrings.CustomDataElementName.Length);
return raw.Substring(SCConstants.CustomDataElementName.Length);
#endif
}

Expand All @@ -247,7 +248,7 @@ private void SetCustomData(string value)
}

using var customXmlStreamReader = new StreamWriter(customXmlPartStream);
customXmlStreamReader.Write($"{ConstantStrings.CustomDataElementName}{value}");
customXmlStreamReader.Write($"{SCConstants.CustomDataElementName}{value}");
}

private CustomXmlPart GetSldCustomXmlPart()
Expand All @@ -256,7 +257,7 @@ private CustomXmlPart GetSldCustomXmlPart()
{
using var customXmlPartStream = new StreamReader(customXmlPart.GetStream());
string customXmlPartText = customXmlPartStream.ReadToEnd();
if (customXmlPartText.StartsWith(ConstantStrings.CustomDataElementName,
if (customXmlPartText.StartsWith(SCConstants.CustomDataElementName,
StringComparison.CurrentCulture))
{
return customXmlPart;
Expand Down
5 changes: 3 additions & 2 deletions ShapeCrawler/PowerPoint/Shape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using DocumentFormat.OpenXml;
using ShapeCrawler.Constants;
using ShapeCrawler.Exceptions;
using ShapeCrawler.Extensions;
using ShapeCrawler.Placeholders;
Expand Down Expand Up @@ -133,13 +134,13 @@ public void ThrowIfRemoved()
private void SetCustomData(string value)
{
string customDataElement =
$@"<{ConstantStrings.CustomDataElementName}>{value}</{ConstantStrings.CustomDataElementName}>";
$@"<{SCConstants.CustomDataElementName}>{value}</{SCConstants.CustomDataElementName}>";
this.PShapeTreesChild.InnerXml += customDataElement;
}

private string? GetCustomData()
{
var pattern = @$"<{ConstantStrings.CustomDataElementName}>(.*)<\/{ConstantStrings.CustomDataElementName}>";
var pattern = @$"<{SCConstants.CustomDataElementName}>(.*)<\/{SCConstants.CustomDataElementName}>";
var regex = new Regex(pattern);
var elementText = regex.Match(this.PShapeTreesChild.InnerXml).Groups[1];
if (elementText.Value.Length == 0)
Expand Down
7 changes: 7 additions & 0 deletions ShapeCrawler/Services/FontService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Linq;
using Microsoft.VisualBasic;
using ShapeCrawler.Constants;
using SkiaSharp;

namespace ShapeCrawler.Services
Expand Down Expand Up @@ -44,6 +46,11 @@ internal static int GetAdjustedFontSize(string text, IFont font, Shape shape)

if (wordY > wordMaxY)
{
if (paint.TextSize == SCConstants.MinReduceFontSize)
{
break;
}

paint.TextSize = --paint.TextSize;
wordX = rect.Left;
wordY = rect.Top + paint.TextSize;
Expand Down
7 changes: 0 additions & 7 deletions ShapeCrawler/Statics/ConstantStrings.cs

This file was deleted.

9 changes: 0 additions & 9 deletions ShapeCrawler/Statics/FormatConstants.cs

This file was deleted.

0 comments on commit 41e31e8

Please sign in to comment.