[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master dbe5955 015/156: Factor out html_interpolator
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master dbe5955 015/156: Factor out html_interpolator from pdf_illustration |
Date: |
Tue, 30 Jan 2018 17:21:52 -0500 (EST) |
branch: master
commit dbe5955d37ed8df2cd7e4266e962dec63f9644e4
Author: Vadim Zeitlin <address@hidden>
Commit: Vadim Zeitlin <address@hidden>
Factor out html_interpolator from pdf_illustration
This allows to provide not just interpolation, but also test_variable()
which is useful for checking synthetic variables (i.e. those not
existing in the ledger itself) values in the pages code.
---
ledger_pdf_generator_wx.cpp | 141 +++++++++++++++++++++++++++++++-------------
1 file changed, 100 insertions(+), 41 deletions(-)
diff --git a/ledger_pdf_generator_wx.cpp b/ledger_pdf_generator_wx.cpp
index 2d905b7..1b02767 100644
--- a/ledger_pdf_generator_wx.cpp
+++ b/ledger_pdf_generator_wx.cpp
@@ -38,6 +38,7 @@
#include <wx/pdfdc.h>
#include <map>
+#include <stdexcept>
LMI_FORCE_LINKING_IN_SITU(ledger_pdf_generator_wx)
@@ -46,39 +47,19 @@ using namespace html;
namespace
{
-// This is just a container for the illustration-global data.
-class pdf_illustration
+// Helper class grouping functions for dealing with interpolating strings
+// containing variable references.
+class html_interpolator
{
public:
- pdf_illustration(Ledger const& ledger
- ,fs::path const& output
- )
- :writer_(output.string(), wxPORTRAIT, &html_font_sizes)
- ,dc_(writer_.dc())
- ,ledger_(ledger)
+ // Ctor takes the object used to interpolate the variables not explicitly
+ // defined using add_variable(). Its lifetime must be greater than that of
+ // this object itself.
+ explicit html_interpolator(LedgerInvariant const& invar)
+ :invar_(invar)
{
- init_variables();
- }
-
- // Add a new page using its render() method.
- template<typename T>
- void add()
- {
- if(page_number_++)
- {
- dc_.StartPage();
- }
-
- T page;
- page.render
- (ledger_
- ,writer_
- ,dc_
- ,[this](char const *s) { return interpolate_html(s); }
- );
}
- protected:
// A method which can be used to interpolate an HTML string containing
// references to the variables defined for this illustration. The general
// syntax is the same as in the global interpolate_string() function, i.e.
@@ -88,7 +69,7 @@ class pdf_illustration
// - Special variables defined in this class, such as "lmi_version" and
// "date_prepared".
// - Any additional fields defined in the derived classes.
- text interpolate_html(char const* s) const
+ text operator()(char const* s) const
{
return text::from_html
(interpolate_string
@@ -98,10 +79,58 @@ class pdf_illustration
);
}
+ // Add a variable, providing either its raw text or already escaped HTML
+ // representation. Boolean values are converted to strings "0" or "1" as
+ // expected.
+ void add_variable(std::string const& name, text const& value)
+ {
+ vars_[name] = value;
+ }
+
+ void add_variable(std::string const& name, std::string const& value)
+ {
+ add_variable(name, text::from(value));
+ }
+
+ void add_variable(std::string const& name, bool value)
+ {
+ add_variable(name, std::string(value ? "1" : "0"));
+ }
+
+ // Test a boolean variable: the value must be "0" or "1", which is mapped
+ // to false or true respectively. Anything else results in an exception.
+ bool test_variable(std::string const& name) const
+ {
+ auto const z = expand_simple_html(name).as_html();
+ return
+ z == "1" ? true
+ : z == "0" ? false
+ : throw std::runtime_error
+ ("Variable '" + name + "' has non-boolean value '" + z + "'"
+ )
+ ;
+ }
+
private:
// Highest level variable expansion function.
text expand_html(std::string const& s) const
{
+ // Check for the special "${var?only-if-set}" form:
+ auto const pos_question = s.find('?');
+ if(pos_question != std::string::npos)
+ {
+ return test_variable(s.substr(0, pos_question))
+ ? text::from(s.substr(pos_question + 1))
+ : text()
+ ;
+ }
+
+ return expand_simple_html(s);
+ }
+
+ // Simple expansion for just the variable name.
+ text expand_simple_html(std::string const& s) const
+ {
// Check our own variables first:
auto const it = vars_.find(s);
if(it != vars_.end())
@@ -110,9 +139,45 @@ class pdf_illustration
}
// Then look in the ledger.
- return text::from(ledger_.GetLedgerInvariant().value_str(s));
+ return text::from(invar_.value_str(s));
+ }
+
+ // Object used for variables expansion.
+ LedgerInvariant const& invar_;
+
+ // Variables defined for all pages of this illustration.
+ std::map<std::string, text> vars_;
+};
+
+// This is just a container for the illustration-global data.
+class pdf_illustration : protected html_interpolator
+{
+ public:
+ pdf_illustration(Ledger const& ledger
+ ,fs::path const& output
+ )
+ :html_interpolator(ledger.GetLedgerInvariant())
+ ,writer_(output.string(), wxPORTRAIT, &html_font_sizes)
+ ,dc_(writer_.dc())
+ ,ledger_(ledger)
+ {
+ init_variables();
}
+ // Add a new page using its render() method.
+ template<typename T>
+ void add()
+ {
+ if(page_number_++)
+ {
+ dc_.StartPage();
+ }
+
+ T page;
+ page.render(ledger_, writer_, dc_, *this);
+ }
+
+ private:
// Initialize the variables that can be interpolated later.
void init_variables()
{
@@ -137,14 +202,15 @@ class pdf_illustration
);
}
- vars_["lmi_version"] = text::from(lmi_version);
- vars_["date_prepared"] =
- text::from(month_name(prep_date.month()))
+ add_variable("lmi_version", lmi_version);
+ add_variable
+ ("date_prepared"
+ , text::from(month_name(prep_date.month()))
+ text::nbsp()
+ text::from(value_cast<std::string>(prep_date.day()))
+ text::from(", ")
+ text::from(value_cast<std::string>(prep_date.year()))
- ;
+ );
}
// Use non-default font sizes to make it simpler to replicate the existing
@@ -161,9 +227,6 @@ class pdf_illustration
// Source of the data.
Ledger const& ledger_;
- // Variables defined for all pages of this illustration.
- std::map<std::string, text> vars_;
-
// Number of last added page.
int page_number_{0};
};
@@ -178,10 +241,6 @@ std::array<int, 7> const pdf_illustration::html_font_sizes
=
,20
};
-// Type of function which can be used to interpolate variables in an HTML
-// string.
-using html_interpolator = std::function<text (char const* s)>;
-
class page
{
public:
- [lmi-commits] [lmi] master 783befa 006/156: Add separate class for representing HTML contents, (continued)
- [lmi-commits] [lmi] master 783befa 006/156: Add separate class for representing HTML contents, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 8c5be11 128/156: Use proper types for get_two_column_header() parameters, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 257ff4b 065/156: Add numeric summary table to PDF illustrations, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master ef38c9d 141/156: Revert the title map related changes, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master b1ab0fa 126/156: Leave a gap between upper footer part and main page contents, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 940198c 059/156: Add numeric summary attachment page, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master b341a2a 061/156: Factor out using_illustration_table helper class, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 1b46585 076/156: Use MarketingNameFootnote & StateMarketingImprimatur on cover page, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 234cd39 012/156: Use custom font sizes to be closer to the existing illustrations, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 956fcca 071/156: Change the second narrative summary page to use a template too, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master dbe5955 015/156: Factor out html_interpolator from pdf_illustration,
Greg Chicares <=
- [lmi-commits] [lmi] master 9665573 070/156: Change narrative summary page to use an external template, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master a629602 083/156: Use custom <scaled_image> HTML tag for the embedded images, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master b425030 082/156: Factor out html_cell_for_pdf_output from numeric_summary_table_cell, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master d99576a 069/156: Change cover page to use an external template, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 416ab02 030/156: Add support for vector variables to PDF generating code, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master d4dfaa9 075/156: Also use data directory for image files referenced from HTML, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 4f98db5 081/156: Don't show "Age 70" row in numeric summary for composites, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master f8853b9 090/156: Add "contract numbers" fragment to the header, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 61430d2 092/156: Move some variable definitions to the base illustration class, Greg Chicares, 2018/01/30
- [lmi-commits] [lmi] master 7ccd207 087/156: Rename "footer_contents" to more precise "page_number", Greg Chicares, 2018/01/30