Added Box element, Redesigned Debug element, Added image placeholder
This commit is contained in:
@@ -38,7 +38,7 @@ namespace QuestPDF.Examples
|
||||
.Background("#DDD")
|
||||
.Padding(10)
|
||||
.ExtendVertical()
|
||||
.Text(TextPlaceholder.LoremIpsum());
|
||||
.Text(Helpers.Placeholders.LoremIpsum());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace QuestPDF.UnitTests
|
||||
[TestFixture]
|
||||
public class DebugTests
|
||||
{
|
||||
[Test]
|
||||
public void Measure_ShouldHandleNullChild() => new Debug().MeasureWithoutChild();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user