Added Box element, Redesigned Debug element, Added image placeholder

This commit is contained in:
Marcin Ziąbek
2021-04-18 23:11:29 +02:00
parent 950d971119
commit f77d8baa63
19 changed files with 259 additions and 68 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ namespace QuestPDF.Examples
.Background("#DDD")
.Padding(10)
.ExtendVertical()
.Text(TextPlaceholder.LoremIpsum());
.Text(Helpers.Placeholders.LoremIpsum());
});
}
+2 -2
View File
@@ -34,8 +34,8 @@ namespace QuestPDF.Examples
{
stack.Element().Row(row =>
{
row.RelativeColumn(2).LabelCell().Text(TextPlaceholder.Label());
row.RelativeColumn(3).ValueCell().Text(TextPlaceholder.Paragraph());
row.RelativeColumn(2).LabelCell().Text(Placeholders.Label());
row.RelativeColumn(3).ValueCell().Text(Placeholders.Paragraph());
});
}
});
+4 -4
View File
@@ -52,7 +52,7 @@ namespace QuestPDF.ReportSample
return new ReportSection
{
Title = TextPlaceholder.Label(),
Title = Placeholders.Label(),
Parts = Enumerable.Range(0, sectionLength).Select(x => GetRandomElement()).ToList()
};
}
@@ -74,8 +74,8 @@ namespace QuestPDF.ReportSample
{
return new ReportSectionText
{
Label = TextPlaceholder.Label(),
Text = TextPlaceholder.Paragraph()
Label = Placeholders.Label(),
Text = Placeholders.Paragraph()
};
}
@@ -113,7 +113,7 @@ namespace QuestPDF.ReportSample
{
PhotoData = Helpers.GetPhoto($"{photoId}.jpg"),
Comments = TextPlaceholder.Paragraph(),
Comments = Placeholders.Paragraph(),
Date = DateTime.Now - TimeSpan.FromDays(Helpers.Random.NextDouble() * 100),
Location = Helpers.RandomLocation(),
@@ -30,14 +30,14 @@ namespace QuestPDF.ReportSample.Layouts
container
.Row(row =>
{
row.RelativeColumn(2).Component(new ImageTemplate(Model.PhotoData));
row.RelativeColumn(2).AspectRatio(4 / 3f).Image(Placeholders.Image);
row.RelativeColumn().PaddingLeft(5).Stack(stack =>
{
stack.Spacing(7f);
stack.Element().Component(new ImageTemplate(Model.MapDetailsSource));
stack.Element().Component(new ImageTemplate(Model.MapContextSource));
stack.Element().AspectRatio(4 / 3f).Image(Placeholders.Image);
stack.Element().AspectRatio(4 / 3f).Image(Placeholders.Image);
});
});
}
@@ -59,7 +59,7 @@ namespace QuestPDF.ReportSample.Layouts
{
stack.Spacing(5);
stack.Element().Component(new ImageTemplate(model.ImageSource));
stack.Element().MaxWidth(250).AspectRatio(4 / 3f).Image(Placeholders.Image);
stack.Element().Text(model.Location.Format(), Typography.Normal);
});
}
@@ -72,12 +72,12 @@ namespace QuestPDF.ReportSample.Layouts
return;
}
container.Debug().Debug().Grid(grid =>
container.Debug("Photo gallery").Grid(grid =>
{
grid.Spacing(5);
grid.Columns(3);
model.Photos.ForEach(x => grid.Element().Component(new ImageTemplate(x)));
model.Photos.ForEach(x => grid.Element().AspectRatio(4 / 3f).Image(Placeholders.Image));
});
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ namespace QuestPDF.ReportSample
public void PerformanceBenchmark()
{
// test size
const int testSize = 250;
const int testSize = 100;
const decimal performanceTarget = 5; // documents per second
// create report models
+5 -4
View File
@@ -1,5 +1,6 @@
using NUnit.Framework;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -17,10 +18,10 @@ namespace QuestPDF.UnitTests
TestPlan
.For(x => new Background
{
Color = "#F00"
Color = Colors.Red.Medium
})
.DrawElement(new Size(400, 300))
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), "#F00")
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
.CheckDrawResult();
}
@@ -30,11 +31,11 @@ namespace QuestPDF.UnitTests
TestPlan
.For(x => new Background
{
Color = "#F00",
Color = Colors.Red.Medium,
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), "#F00")
.ExpectCanvasDrawRectangle(new Position(0, 0), new Size(400, 300), Colors.Red.Medium)
.ExpectChildDraw(new Size(400, 300))
.CheckDrawResult();
}
+6 -5
View File
@@ -1,6 +1,7 @@
using NUnit.Framework;
using QuestPDF.Drawing.SpacePlan;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using QuestPDF.UnitTests.TestEngine;
@@ -41,16 +42,16 @@ namespace QuestPDF.UnitTests
Bottom = 30,
Left = 40,
Color = "#FF0000",
Color = Colors.Red.Medium,
Child = x.CreateChild()
})
.DrawElement(new Size(400, 300))
.ExpectChildDraw(new Size(400, 300))
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(430, 10), "#FF0000") // top
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(40, 320), "#FF0000") // left
.ExpectCanvasDrawRectangle(new Position(-20, 285), new Size(430, 30), "#FF0000") // bottom
.ExpectCanvasDrawRectangle(new Position(390, -5), new Size(20, 320), "#FF0000") // right
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(430, 10), Colors.Red.Medium) // top
.ExpectCanvasDrawRectangle(new Position(-20, -5), new Size(40, 320), Colors.Red.Medium) // left
.ExpectCanvasDrawRectangle(new Position(-20, 285), new Size(430, 30), Colors.Red.Medium) // bottom
.ExpectCanvasDrawRectangle(new Position(390, -5), new Size(20, 320), Colors.Red.Medium) // right
.ExpectChildDraw(new Size(400, 300))
.CheckDrawResult();
}
+1 -2
View File
@@ -7,7 +7,6 @@ namespace QuestPDF.UnitTests
[TestFixture]
public class DebugTests
{
[Test]
public void Measure_ShouldHandleNullChild() => new Debug().MeasureWithoutChild();
}
}
+2 -1
View File
@@ -1,10 +1,11 @@
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Background : ContainerElement
{
public string Color { get; set; } = "#00000000";
public string Color { get; set; } = Colors.Black;
internal override void Draw(ICanvas canvas, Size availableSpace)
{
+2 -1
View File
@@ -1,10 +1,11 @@
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Border : ContainerElement
{
public string Color { get; set; } = "#000000";
public string Color { get; set; } = Colors.Black;
public float Top { get; set; }
public float Right { get; set; }
+17
View File
@@ -0,0 +1,17 @@
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Box : ContainerElement
{
internal override void Draw(ICanvas canvas, Size availableSpace)
{
var targetSize = Child?.Measure(availableSpace) as Size;
if (targetSize == null)
return;
Child?.Draw(canvas, targetSize);
}
}
}
+25 -26
View File
@@ -1,37 +1,36 @@
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Elements
{
internal class Debug : ContainerElement
internal class Debug : IComponent
{
private static readonly TextStyle TextStyle = TextStyle.Default.Color("#F00").FontType("Consolas").Size(10);
public IElement? Child { get; set; }
internal override void Draw(ICanvas canvas, Size availableSpace)
public string Text { get; set; }
public string Color { get; set; } = Colors.Red.Medium;
public void Compose(IContainer container)
{
Child?.Draw(canvas, availableSpace);
DrawBoundingBox();
DrawDimensions();
void DrawBoundingBox()
{
// TODO: when layer element is done, move this code into fluent API
var container = new Container();
container
.Border(1)
.BorderColor("#FF0000")
.Background("#33FF0000");
container.Draw(canvas, availableSpace);
}
void DrawDimensions()
{
canvas.DrawText($"W: {availableSpace.Width:F1}", new Position(5, 12), TextStyle);
canvas.DrawText($"H: {availableSpace.Height:F1}", new Position(5, 22), TextStyle);
}
var backgroundColor = SKColor.Parse(Color).WithAlpha(75).ToString();
container
.Border(1)
.BorderColor(Color)
.Layers(layers =>
{
layers.PrimaryLayer().Element(Child);
layers.Layer().Background(backgroundColor);
layers
.Layer()
.ShowIf(!string.IsNullOrWhiteSpace(Text))
.Box()
.Background(Colors.White)
.Padding(2)
.Text(Text, TextStyle.Default.Color(Color).FontType("Consolas").Size(8));
});
}
}
}
+11 -2
View File
@@ -1,10 +1,12 @@
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Elements
{
internal class Placeholder : IComponent
{
public string Text { get; set; }
private static readonly byte[] ImageData;
static Placeholder()
@@ -15,11 +17,18 @@ namespace QuestPDF.Elements
public void Compose(IContainer container)
{
container
.Background("CCC")
.Background(Colors.Grey.Lighten2)
.AlignMiddle()
.AlignCenter()
.Padding(5)
.MaxHeight(32)
.Image(ImageData, ImageScaling.FitArea);
.Element(x =>
{
if (string.IsNullOrWhiteSpace(Text))
x.Image(ImageData, ImageScaling.FitArea);
else
x.Text(Text, TextStyle.Default.Size(14).SemiBold());
});
}
}
}
+33
View File
@@ -0,0 +1,33 @@
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
{
public static class DebugExtensions
{
public static IContainer Debug(this IContainer parent, string text, string color)
{
var container = new Container();
parent.Component(new Debug
{
Child = container,
Text = text,
Color = color
});
return container;
}
public static IContainer Debug(this IContainer parent, string text)
{
return parent.Debug(text, Colors.Red.Medium);
}
public static IContainer Debug(this IContainer parent)
{
return parent.Debug(string.Empty, Colors.Red.Medium);
}
}
}
+12 -8
View File
@@ -1,6 +1,7 @@
using System;
using QuestPDF.Drawing.Exceptions;
using QuestPDF.Elements;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Fluent
@@ -40,11 +41,6 @@ namespace QuestPDF.Fluent
{
return handler(parent);
}
public static IContainer Debug(this IContainer parent)
{
return parent.Element(new Debug());
}
public static void PageNumber(this IContainer element, string textFormat = "{number}", TextStyle? style = null)
{
@@ -71,10 +67,13 @@ namespace QuestPDF.Fluent
Color = color
});
}
public static void Placeholder(this IContainer element)
public static void Placeholder(this IContainer element, string? text = null)
{
element.Component<Placeholder>();
element.Component(new Elements.Placeholder
{
Text = text ?? string.Empty
});
}
public static IContainer ShowOnce(this IContainer element)
@@ -159,5 +158,10 @@ namespace QuestPDF.Fluent
Handler = handler
});
}
public static IContainer Box(this IContainer element)
{
return element.Element(new Box());
}
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ namespace QuestPDF.Fluent
}
}
public static void DynamicImage(this IContainer element, Func<Size, byte[]> imageSource)
public static void Image(this IContainer element, Func<Size, byte[]> imageSource)
{
element.Element(new DynamicImage
{
@@ -1,9 +1,12 @@
using System;
using System.Linq;
using QuestPDF.Drawing;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Helpers
{
public static class TextPlaceholder
public static class Placeholders
{
private static Random Random = new Random();
@@ -148,5 +151,126 @@ namespace QuestPDF.Helpers
public static string Percent() => (Random.NextDouble() * 100).ToString("N0") + "%";
#endregion
#region Visual
private static readonly string[] BackgroundColors =
{
Colors.Red.Lighten2,
Colors.Pink.Lighten2,
Colors.Purple.Lighten2,
Colors.DeepPurple.Lighten2,
Colors.Indigo.Lighten2,
Colors.Blue.Lighten2,
Colors.LightBlue.Lighten2,
Colors.Cyan.Lighten2,
Colors.Teal.Lighten2,
Colors.Green.Lighten2,
Colors.LightGreen.Lighten2,
Colors.Lime.Lighten2,
Colors.Yellow.Lighten2,
Colors.Amber.Lighten2,
Colors.Orange.Lighten2,
Colors.DeepOrange.Lighten2,
Colors.Brown.Lighten2,
Colors.Grey.Lighten2,
Colors.BlueGrey.Lighten2
};
public static string BackgroundColor()
{
var index = Random.Next(0, BackgroundColors.Length);
return BackgroundColors[index];
}
public static string Color()
{
var colors = new[]
{
Colors.Red.Medium,
Colors.Pink.Medium,
Colors.Purple.Medium,
Colors.DeepPurple.Medium,
Colors.Indigo.Medium,
Colors.Blue.Medium,
Colors.LightBlue.Medium,
Colors.Cyan.Medium,
Colors.Teal.Medium,
Colors.Green.Medium,
Colors.LightGreen.Medium,
Colors.Lime.Medium,
Colors.Yellow.Medium,
Colors.Amber.Medium,
Colors.Orange.Medium,
Colors.DeepOrange.Medium,
Colors.Brown.Medium,
Colors.Grey.Medium,
Colors.BlueGrey.Medium
};
var index = Random.Next(0, colors.Length);
return colors[index];
}
public static byte[] Image(Size size)
{
// shuffle corner positions
var targetPositions = new[]
{
new SKPoint(0, 0),
new SKPoint(size.Width, 0),
new SKPoint(0, size.Height),
new SKPoint(size.Width, size.Height)
};
var positions = targetPositions
.OrderBy(x => Random.Next())
.ToList();
// rand and shuffle colors
var colors = BackgroundColors
.OrderBy(x => Random.Next())
.Take(4)
.Select(SKColor.Parse)
.ToArray();
// create image with white background
var imageInfo = new SKImageInfo((int)size.Width, (int)size.Height);
using var surface = SKSurface.Create(imageInfo);
using var backgroundPaint = new SKPaint
{
Color = SKColors.White
};
surface.Canvas.DrawRect(0, 0, size.Width, size.Height, backgroundPaint);
// draw gradient
SKShader GetForegroundShader(int index)
{
var radius = Math.Max(size.Width, size.Height);
var color = colors[index];
return SKShader.CreateRadialGradient(
positions[index], radius,
new[] {color, color.WithAlpha(0)}, new[] {0, 1f},
SKShaderTileMode.Decal);
}
using var shaderPaint = new SKPaint
{
Shader = SKShader.CreateCompose(
SKShader.CreateCompose(GetForegroundShader(0), GetForegroundShader(1)),
SKShader.CreateCompose(GetForegroundShader(2), GetForegroundShader(3)))
};
surface.Canvas.DrawRect(0, 0, size.Width, size.Height, shaderPaint);
// return result as an image
surface.Canvas.Save();
return surface.Snapshot().Encode(SKEncodedImageFormat.Jpeg, 90).ToArray();
}
#endregion
}
}
+5 -3
View File
@@ -1,9 +1,11 @@
namespace QuestPDF.Infrastructure
using QuestPDF.Helpers;
namespace QuestPDF.Infrastructure
{
public class TextStyle
{
internal string Color { get; set; } = "#000000";
internal string FontType { get; set; } = "Helvetica";
internal string Color { get; set; } = Colors.Black;
internal string FontType { get; set; } = "Calibri";
internal float Size { get; set; } = 12;
internal float LineHeight { get; set; } = 1.2f;
internal HorizontalAlignment Alignment { get; set; } = HorizontalAlignment.Left;