- Renamed all references from zpdf to zcatpdf
- Module import: @import("zcatpdf")
- Consistent with zcatui, zcatgui naming convention
- All lowercase per Zig standards
Note: Directory rename (zpdf -> zcatpdf) and Forgejo repo rename
should be done manually after this commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
225 lines
9.3 KiB
Zig
225 lines
9.3 KiB
Zig
//! Template Demo - Using predefined document templates
|
|
//!
|
|
//! Run with: zig build template_demo && ./zig-out/bin/template_demo
|
|
|
|
const std = @import("std");
|
|
const zcatpdf = @import("zcatpdf");
|
|
|
|
pub fn main() !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
std.debug.print("=== zcatpdf Template Demo ===\n\n", .{});
|
|
|
|
// Create invoice using template
|
|
try createInvoiceFromTemplate(allocator);
|
|
|
|
// Create letter using template
|
|
try createLetterFromTemplate(allocator);
|
|
|
|
std.debug.print("\nTemplate demo completed successfully!\n", .{});
|
|
}
|
|
|
|
fn createInvoiceFromTemplate(allocator: std.mem.Allocator) !void {
|
|
std.debug.print("Creating invoice from template...\n", .{});
|
|
|
|
// Get the invoice template
|
|
var tmpl = try zcatpdf.Template.invoiceTemplate(allocator);
|
|
defer tmpl.deinit();
|
|
|
|
std.debug.print(" Template: {s}\n", .{tmpl.name});
|
|
std.debug.print(" Page size: {d:.0} x {d:.0} points\n", .{ tmpl.page_width, tmpl.page_height });
|
|
|
|
// Create PDF based on template
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{});
|
|
defer pdf.deinit();
|
|
|
|
pdf.setTitle("Invoice from Template");
|
|
|
|
var page = try pdf.addPageCustom(tmpl.page_width, tmpl.page_height);
|
|
|
|
// Use template regions to position content
|
|
if (tmpl.getRegion("header")) |region| {
|
|
std.debug.print(" Header region: ({d:.0}, {d:.0}) {d:.0}x{d:.0}\n", .{ region.x, region.y, region.width, region.height });
|
|
try page.setFont(.helvetica_bold, 20);
|
|
try page.drawText(region.x, region.y, "ACME Corporation");
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y - 15, "123 Business Street");
|
|
try page.drawText(region.x, region.y - 27, "Tech City, TC 12345");
|
|
}
|
|
|
|
if (tmpl.getRegion("invoice_info")) |region| {
|
|
std.debug.print(" Invoice info region: ({d:.0}, {d:.0})\n", .{ region.x, region.y });
|
|
try page.setFont(.helvetica_bold, 14);
|
|
try page.drawText(region.x, region.y, "INVOICE #2024-001");
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y - 15, "Date: December 9, 2024");
|
|
try page.drawText(region.x, region.y - 27, "Due: December 23, 2024");
|
|
}
|
|
|
|
if (tmpl.getRegion("customer")) |region| {
|
|
std.debug.print(" Customer region: ({d:.0}, {d:.0})\n", .{ region.x, region.y });
|
|
try page.setFont(.helvetica_bold, 12);
|
|
try page.drawText(region.x, region.y, "Bill To:");
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y - 15, "Customer Company Ltd.");
|
|
try page.drawText(region.x, region.y - 27, "456 Client Avenue");
|
|
try page.drawText(region.x, region.y - 39, "Business Town, BT 67890");
|
|
}
|
|
|
|
if (tmpl.getRegion("items")) |region| {
|
|
std.debug.print(" Items region: ({d:.0}, {d:.0}) {d:.0}x{d:.0}\n", .{ region.x, region.y, region.width, region.height });
|
|
|
|
// Draw table header
|
|
page.setFillColor(zcatpdf.Color.hex(0xE0E0E0));
|
|
try page.fillRect(region.x, region.y + region.height - 25, region.width, 25);
|
|
|
|
page.setFillColor(zcatpdf.Color.black);
|
|
try page.setFont(.helvetica_bold, 10);
|
|
try page.drawText(region.x + 5, region.y + region.height - 17, "Description");
|
|
try page.drawText(region.x + 250, region.y + region.height - 17, "Qty");
|
|
try page.drawText(region.x + 320, region.y + region.height - 17, "Price");
|
|
try page.drawText(region.x + 420, region.y + region.height - 17, "Total");
|
|
|
|
// Draw table rows
|
|
try page.setFont(.helvetica, 10);
|
|
const items = [_]struct { desc: []const u8, qty: []const u8, price: []const u8, total: []const u8 }{
|
|
.{ .desc = "Web Development Services", .qty = "40", .price = "$75.00", .total = "$3,000.00" },
|
|
.{ .desc = "UI/UX Design", .qty = "20", .price = "$85.00", .total = "$1,700.00" },
|
|
.{ .desc = "Server Hosting (1 year)", .qty = "1", .price = "$500.00", .total = "$500.00" },
|
|
};
|
|
|
|
var y_offset: f32 = region.y + region.height - 45;
|
|
for (items) |item| {
|
|
try page.drawText(region.x + 5, y_offset, item.desc);
|
|
try page.drawText(region.x + 250, y_offset, item.qty);
|
|
try page.drawText(region.x + 320, y_offset, item.price);
|
|
try page.drawText(region.x + 420, y_offset, item.total);
|
|
y_offset -= 20;
|
|
}
|
|
|
|
// Draw table border
|
|
page.setStrokeColor(zcatpdf.Color.black);
|
|
try page.drawRect(region.x, region.y, region.width, region.height);
|
|
}
|
|
|
|
if (tmpl.getRegion("totals")) |region| {
|
|
std.debug.print(" Totals region: ({d:.0}, {d:.0})\n", .{ region.x, region.y });
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y + 60, "Subtotal:");
|
|
try page.drawText(region.x + 100, region.y + 60, "$5,200.00");
|
|
try page.drawText(region.x, region.y + 45, "Tax (10%):");
|
|
try page.drawText(region.x + 100, region.y + 45, "$520.00");
|
|
|
|
try page.setLineWidth(1);
|
|
try page.drawLine(region.x, region.y + 35, region.x + region.width, region.y + 35);
|
|
|
|
try page.setFont(.helvetica_bold, 12);
|
|
try page.drawText(region.x, region.y + 20, "TOTAL:");
|
|
try page.drawText(region.x + 100, region.y + 20, "$5,720.00");
|
|
}
|
|
|
|
if (tmpl.getRegion("footer")) |region| {
|
|
std.debug.print(" Footer region: ({d:.0}, {d:.0})\n", .{ region.x, region.y });
|
|
try page.setFont(.helvetica, 8);
|
|
page.setFillColor(zcatpdf.Color.hex(0x666666));
|
|
try page.drawText(region.x, region.y + 20, "Payment Terms: Net 14 days");
|
|
try page.drawText(region.x, region.y + 8, "Thank you for your business!");
|
|
}
|
|
|
|
try pdf.save("template_invoice.pdf");
|
|
std.debug.print(" Saved: template_invoice.pdf\n", .{});
|
|
}
|
|
|
|
fn createLetterFromTemplate(allocator: std.mem.Allocator) !void {
|
|
std.debug.print("\nCreating letter from template...\n", .{});
|
|
|
|
// Get the letter template
|
|
var tmpl = try zcatpdf.Template.letterTemplate(allocator);
|
|
defer tmpl.deinit();
|
|
|
|
std.debug.print(" Template: {s}\n", .{tmpl.name});
|
|
|
|
// Create PDF based on template
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{});
|
|
defer pdf.deinit();
|
|
|
|
pdf.setTitle("Letter from Template");
|
|
|
|
var page = try pdf.addPageCustom(tmpl.page_width, tmpl.page_height);
|
|
|
|
// Sender
|
|
if (tmpl.getRegion("sender")) |region| {
|
|
try page.setFont(.helvetica_bold, 11);
|
|
try page.drawText(region.x, region.y, "John Smith");
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y - 14, "123 Sender Street");
|
|
try page.drawText(region.x, region.y - 26, "City, ST 12345");
|
|
try page.drawText(region.x, region.y - 38, "john@example.com");
|
|
}
|
|
|
|
// Date
|
|
if (tmpl.getRegion("date")) |region| {
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y, "December 9, 2024");
|
|
}
|
|
|
|
// Recipient
|
|
if (tmpl.getRegion("recipient")) |region| {
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y, "Ms. Jane Doe");
|
|
try page.drawText(region.x, region.y - 14, "456 Recipient Avenue");
|
|
try page.drawText(region.x, region.y - 26, "Town, ST 67890");
|
|
}
|
|
|
|
// Subject
|
|
if (tmpl.getRegion("subject")) |region| {
|
|
try page.setFont(.helvetica_bold, 11);
|
|
try page.drawText(region.x, region.y, "Re: Project Proposal Discussion");
|
|
}
|
|
|
|
// Body
|
|
if (tmpl.getRegion("body")) |region| {
|
|
try page.setFont(.helvetica, 10);
|
|
const line_height: f32 = 14;
|
|
var y = region.y + region.height;
|
|
|
|
try page.drawText(region.x, y, "Dear Ms. Doe,");
|
|
y -= line_height * 2;
|
|
|
|
try page.drawText(region.x, y, "I am writing to follow up on our recent conversation regarding the");
|
|
y -= line_height;
|
|
try page.drawText(region.x, y, "proposed collaboration between our organizations. I believe there is");
|
|
y -= line_height;
|
|
try page.drawText(region.x, y, "significant potential for a mutually beneficial partnership.");
|
|
y -= line_height * 2;
|
|
|
|
try page.drawText(region.x, y, "As discussed, I have prepared a detailed proposal outlining the scope");
|
|
y -= line_height;
|
|
try page.drawText(region.x, y, "of work, timeline, and expected outcomes. I would be happy to schedule");
|
|
y -= line_height;
|
|
try page.drawText(region.x, y, "a meeting at your earliest convenience to discuss this further.");
|
|
y -= line_height * 2;
|
|
|
|
try page.drawText(region.x, y, "Please do not hesitate to contact me if you have any questions or");
|
|
y -= line_height;
|
|
try page.drawText(region.x, y, "require additional information.");
|
|
y -= line_height * 2;
|
|
|
|
try page.drawText(region.x, y, "Thank you for your time and consideration.");
|
|
}
|
|
|
|
// Signature
|
|
if (tmpl.getRegion("signature")) |region| {
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y + 50, "Sincerely,");
|
|
try page.setFont(.helvetica_bold, 10);
|
|
try page.drawText(region.x, region.y + 20, "John Smith");
|
|
try page.setFont(.helvetica, 10);
|
|
try page.drawText(region.x, region.y + 6, "Senior Consultant");
|
|
}
|
|
|
|
try pdf.save("template_letter.pdf");
|
|
std.debug.print(" Saved: template_letter.pdf\n", .{});
|
|
}
|