lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master f950086 07/10: Split some code into new sourc


From: Greg Chicares
Subject: [lmi-commits] [lmi] master f950086 07/10: Split some code into new source files, adding an inchoate unit test
Date: Fri, 27 Jul 2018 17:03:56 -0400 (EDT)

branch: master
commit f95008675833861e5e62632b6eb9183ca1523c11
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Split some code into new source files, adding an inchoate unit test
---
 Makefile.am            |   9 ++
 objects.make           |   7 ++
 report_table.cpp       | 232 ++++++++++++++++++++++++++++++++++++++
 report_table.hpp       | 120 ++++++++++++++++++++
 report_table_test.cpp  |  31 ++++++
 wx_table_generator.cpp | 294 -------------------------------------------------
 wx_table_generator.hpp |   3 +-
 7 files changed, 400 insertions(+), 296 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index c9d159a..bd2fcdb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -130,6 +130,7 @@ TESTS = \
     test_progress_meter \
     test_rate_table \
     test_regex \
+    test_report_table \
     test_round \
     test_round_to \
     test_rtti_lmi \
@@ -423,6 +424,7 @@ liblmi_la_SOURCES = \
     mortality_rates_fetch.cpp \
     preferences_model.cpp \
     product_data.cpp \
+    report_table.cpp \
     rounding_rules.cpp \
     stratified_algorithms.cpp \
     stratified_charges.cpp \
@@ -1004,6 +1006,12 @@ test_regex_CXXFLAGS = $(AM_CXXFLAGS)
 test_regex_LDADD = \
   $(BOOST_LIBS)
 
+test_report_table_SOURCES = \
+  $(common_test_objects) \
+  report_table.cpp \
+  report_table_test.cpp
+test_report_table_CXXFLAGS = $(AM_CXXFLAGS)
+
 test_round_SOURCES = \
   $(common_test_objects) \
   round_glibc.cpp \
@@ -1281,6 +1289,7 @@ noinst_HEADERS = \
     product_data.hpp \
     product_editor.hpp \
     progress_meter.hpp \
+    report_table.hpp \
     round_to.hpp \
     rounding_document.hpp \
     rounding_rules.hpp \
diff --git a/objects.make b/objects.make
index baec96a..964b70e 100644
--- a/objects.make
+++ b/objects.make
@@ -309,6 +309,7 @@ lmi_common_objects := \
   mortality_rates_fetch.o \
   preferences_model.o \
   product_data.o \
+  report_table.o \
   rounding_rules.o \
   stratified_algorithms.o \
   stratified_charges.o \
@@ -453,6 +454,7 @@ unit_test_targets := \
   progress_meter_test \
   rate_table_test \
   regex_test \
+  report_table_test \
   round_test \
   round_to_test \
   rtti_lmi_test \
@@ -888,6 +890,11 @@ regex_test$(EXEEXT): \
   regex_test.o \
   timer.o \
 
+report_table_test$(EXEEXT): \
+  $(common_test_objects) \
+  report_table.o \
+  report_table_test.o \
+
 round_test$(EXEEXT): \
   $(common_test_objects) \
   round_glibc.o \
diff --git a/report_table.cpp b/report_table.cpp
new file mode 100644
index 0000000..53b68f7
--- /dev/null
+++ b/report_table.cpp
@@ -0,0 +1,232 @@
+// Platform-independent support for report tables.
+//
+// Copyright (C) 2015, 2016, 2017, 2018 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#include "pchfile.hpp"
+
+#include "report_table.hpp"
+
+#include "alert.hpp"
+#include "math_functions.hpp"           // outward_quotient()
+
+/// Compute column widths.
+///
+/// First, allocate adequate width to each inelastic column; then
+/// distribute any excess width left over among elastic columns.
+///
+/// The width of each inelastic column reflects:
+///  - a mask like "999,999" (ideally, there would instead be a
+///    quasi-global data structure mapping symbolic column names
+///    to their corresponding headers and maximal widths)
+///  - the header width
+///  - PDF !! the bilateral margins added as a first step below
+/// The margins may be slightly reduced by this function to make
+/// everything fit when it otherwise wouldn't.
+
+void set_column_widths
+    (int                             total_width
+    ,int                           & column_margin
+    ,std::vector<table_column_info>& all_columns
+    )
+//
+// const    total_width    max table width (page width - page margins)
+// mutable  column_margin  spacing on both left and right of column
+// mutable  all_columns    std::vector<table_column_info>
+//   table_column_info::col_width_ is the only member changed
+{
+    // PDF !! Unconditionally add bilateral margins even though they
+    // may conditionally be removed below. This is a questionable
+    // design decision; if it is later reversed, then remove the
+    // comment about it above the implementation.
+    for(auto& i : all_columns)
+        {
+        if(!i.is_hidden() && !i.is_elastic())
+            {
+            i.col_width_ += 2 * column_margin;
+            }
+        }
+
+    // Number of non-hidden columns.
+    int number_of_columns = 0;
+
+    // Number of non-hidden elastic columns.
+    int number_of_elastic_columns = 0;
+
+    // Total width of all non-hidden inelastic columns.
+    int total_inelastic_width = 0;
+
+    for(auto const& i : all_columns)
+        {
+        if(i.is_hidden())
+            {
+            continue;
+            }
+
+        ++number_of_columns;
+
+        if(i.is_elastic())
+            {
+            ++number_of_elastic_columns;
+            }
+        else
+            {
+            total_inelastic_width += i.col_width();
+            }
+        }
+
+    if(total_width < total_inelastic_width)
+        {
+        // The inelastic columns don't all fit with their original
+        // one-em presumptive bilateral margins. Try to make them fit
+        // by reducing the margins slightly.
+        //
+        // The number of pixels that would need to be removed is:
+        auto const overflow = total_inelastic_width - total_width;
+
+        // Because inelastic columns take more than the available
+        // horizontal space, there's no room to fit any elastic
+        // columns, so the column-fitting problem is overconstrained.
+        // Therefore, don't even try reducing margins if there are any
+        // elastic columns.
+        if(!number_of_elastic_columns)
+            {
+// Also calculate the number of pixels by which it overflows for each column
+            // We need to round up in division here to be sure that all columns
+            // fit into the available width.
+            auto const overflow_per_column = outward_quotient
+                (overflow
+                ,number_of_columns
+                );
+// Now determine whether reducing the margins will make the table fit.
+// If that works, then do it; else don't do it, and print a warning.
+//
+// column_margin is the padding on each side of every column, so
+// the number of pixels between columns, as the table was originally
+// laid out, is two times column_margin--which, as we just determined,
+// was too generous, so we're going to try reducing it.
+// Then this conditional compares
+//   the number of pixels by which we must shrink each column, to
+//   the number of pixels of padding between columns
+// Reducing the padding is a workable strategy if the desired reduction
+// is less than the padding.
+//
+// Is this as good as it can be, given that coordinates are integers?
+// Answer: Yes--the integers count points, not ems or characters, and
+// typographers wouldn't use any finer unit for this task.
+            if(overflow_per_column <= 2 * column_margin)
+                {
+                // We are going to reduce the total width by more than
+                // necessary, in general, because of rounding up above, so
+                // compensate for it by giving 1 extra pixel until we run out
+                // of these "underflow" pixels.
+// Defect: the number of pixels separating columns might now be zero.
+// '9' is five PDF pixels wide; do we need, say, two pixels between columns?
+//
+// Suggestion: change the
+//   overflow_per_column <= column_margin
+// condition to something like:
+//    overflow_per_column <= column_margin - 4 // two pixels on each side
+//    overflow_per_column <= column_margin - 2 // one pixel on each side
+                auto underflow = overflow_per_column * number_of_columns - 
overflow;
+
+                for(auto& i : all_columns)
+                    {
+                    if(i.is_hidden())
+                        {
+                        continue;
+                        }
+
+                    i.col_width_ -= overflow_per_column;
+
+                    if(0 < underflow)
+                        {
+                        ++i.col_width_;
+                        --underflow;
+                        }
+                    }
+
+                column_margin -= (overflow_per_column + 1) / 2;
+
+                // We condensed the columns enough to make them fit, so no need
+                // for the warning and we don't have any elastic columns, so
+                // we're done.
+                return;
+                }
+// If overflow_per_column is 1, then column_margin -= 1
+// "           "          "  2,   "        "           1
+// "           "          "  3,   "        "           2
+// "           "          "  4,   "        "           2
+// The 'underflow' logic shrinks columns by the exact number of pixels
+// to use up all the available width. But the column_margin reduction
+// isn't exact due to truncation: when the margin is added (on both sides),
+// is the total of all (margin+column+margin) widths lower than the maximum,
+// so that this is just a small aesthetic issue, or is it too wide, so that
+// not everything fits?
+//
+// Answer:
+// This is an issue of aligning the column text, not of fitting, because the
+// margin is used when positioning the text inside the column width. And the
+// width is correct, so the worst that can happen here is that the text is
+// offset by 0.5 pixels -- but, of course, if we rounded it down, it would be
+// offset by 0.5 pixels in the other direction. So maybe we should write
+//
+//     column_margin -= overflow_per_column / 2;
+//
+// just because it's shorter and not necessarily worse (nor better).
+            }
+
+        warning()
+            << "Not enough space for all " << number_of_columns << " columns."
+            << "\nPrintable width is " << total_width << " points."
+            << "\nData alone require " << total_inelastic_width - 2 * 
column_margin * number_of_columns
+            << " points without any margins for legibility."
+            << "\nColumn margins of " << column_margin << " points on both 
sides"
+            << " would take up " << 2 * column_margin * number_of_columns << " 
additional points."
+            << LMI_FLUSH
+            ;
+        return;
+        }
+
+    // Lay out elastic columns in whatever space is left over after
+    // accounting for all inelastic columns. Clip to make them fit.
+    //
+    // If there's more than enough space for them, then expand them
+    // to consume all available space.
+    if(number_of_elastic_columns)
+        {
+        int const width_of_each_elastic_column = outward_quotient
+            (total_width - total_inelastic_width
+            ,number_of_elastic_columns
+            );
+
+        for(auto& i : all_columns)
+            {
+            if(i.is_hidden())
+                {
+                continue;
+                }
+
+            if(i.is_elastic())
+                {
+                i.col_width_ = width_of_each_elastic_column;
+                }
+            }
+        }
+}
diff --git a/report_table.hpp b/report_table.hpp
new file mode 100644
index 0000000..e337f6e
--- /dev/null
+++ b/report_table.hpp
@@ -0,0 +1,120 @@
+// Platform-independent support for report tables.
+//
+// Copyright (C) 2015, 2016, 2017, 2018 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#ifndef report_table_hpp
+#define report_table_hpp
+
+#include "config.hpp"
+
+#include "oecumenic_enumerations.hpp"
+#include "so_attributes.hpp"
+
+#include <string>
+#include <vector>
+
+// Elasticity and clipping
+//
+// Most columns are inelastic: they have a fixed minimum width and
+// are not clipped lest crucial information (e.g., part of a number)
+// be lost. The archetypal elastic column is a personal name, whose
+// width is practically unlimited and might even exceed the total page
+// width; it is better to truncate one extremely long personal name
+// than to present an error message and produce no report at all.
+//
+// An ideal report generator might call GetTextExtent() on every row
+// of data to determine a column's ideal width, but this one favors
+// speed by setting a presumptive maximum width for each column.
+// Therefore, it treats a personal-name column as having no natural
+// width at all. Its minimum width might be set equal to its header
+// width, but such a refinement is needless in the problem domain. In
+// the most extreme case, all inelastic columns would fit, but there
+// would be not a single pixel available for elastic columns, which
+// would all in effect be dropped; again, in the problem domain, that
+// would actually be preferable to failing to produce any output.
+//
+// Therefore, elastic columns are clipped, and inelastic ones are not.
+// All other column properties are independent, and specified by
+// arguments, but clipping depends on the elasticity argument. It is
+// distinguished only because clipping is a distinct layout operation.
+//
+//  - is_hidden(): Data for every row of all potential columns are
+//    passed into this class; hidden columns are suppressed so that
+//    they don't appear in the output at all.
+//
+//  - is_elastic(): An elastic column has no innate fixed or preferred
+//    width. After all inelastic columns have claimed their required
+//    widths, any remaining width available is prorated among elastic
+//    columns, which therefore may be wider than their widest contents
+//    or narrower than their narrowest. As a consequence, elastic
+//    columns are clipped--vide supra.
+//
+//  - is_clipped(): A clipped column is truncated to fit its allotted
+//    space. Only elastic columns are clipped--vide supra.
+
+class LMI_SO table_column_info
+{
+  public:
+    table_column_info
+        (std::string      const& header
+        ,int                     width
+        ,oenum_h_align    const  alignment
+        ,oenum_visibility const  visibility
+        ,oenum_elasticity const  elasticity
+        )
+        :col_header_ (header)
+        ,col_width_  (width)
+        ,alignment_  (alignment)
+        ,is_hidden_  (oe_hidden  == visibility)
+        ,is_elastic_ (oe_elastic == elasticity)
+        {
+        }
+
+    std::string const& col_header() const {return col_header_;}
+    int                col_width()  const {return col_width_;}
+    oenum_h_align      alignment()  const {return alignment_;}
+    bool               is_hidden()  const {return is_hidden_;}
+    bool               is_elastic() const {return is_elastic_;}
+    bool               is_clipped() const {return is_elastic();}
+
+  private:
+    std::string   const col_header_;
+
+  public:
+    // PDF !! Modified directly by set_column_widths(), hence neither
+    // private nor const.
+    //
+    // Width in pixels. Because the wxPdfDC uses wxMM_POINTS, each
+    // pixel is one point = 1/72 inch.
+    int col_width_;
+
+  private:
+    oenum_h_align const alignment_;
+    bool          const is_hidden_;
+    bool          const is_elastic_;
+};
+
+void LMI_SO set_column_widths
+    (int                             total_width
+    ,int                           & column_margin
+    ,std::vector<table_column_info>& all_columns
+    );
+
+#endif // report_table_hpp
diff --git a/report_table_test.cpp b/report_table_test.cpp
new file mode 100644
index 0000000..178ef8e
--- /dev/null
+++ b/report_table_test.cpp
@@ -0,0 +1,31 @@
+// Platform-independent support for report tables: unit test.
+//
+// Copyright (C) 2018 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#include "pchfile.hpp"
+
+#include "report_table.hpp"
+
+#include "test_tools.hpp"
+
+int test_main(int, char*[])
+{
+    return EXIT_SUCCESS;
+}
diff --git a/wx_table_generator.cpp b/wx_table_generator.cpp
index a074477..59c5569 100644
--- a/wx_table_generator.cpp
+++ b/wx_table_generator.cpp
@@ -23,9 +23,7 @@
 
 #include "wx_table_generator.hpp"
 
-#include "alert.hpp"
 #include "assert_lmi.hpp"
-#include "math_functions.hpp"           // outward_quotient()
 #include "miscellany.hpp"               // count_newlines(), split_into_lines()
 
 #include <algorithm>                    // max()
@@ -33,93 +31,6 @@
 // Default size of various characters for illustrations and group quotes:
 //   'M' 7pt; 'N' 6pt; '1' 4pt; '9' 4pt; ',' 2pt
 
-// Elasticity and clipping
-//
-// Most columns are inelastic: they have a fixed minimum width and
-// are not clipped lest crucial information (e.g., part of a number)
-// be lost. The archetypal elastic column is a personal name, whose
-// width is practically unlimited and might even exceed the total page
-// width; it is better to truncate one extremely long personal name
-// than to present an error message and produce no report at all.
-//
-// An ideal report generator might call GetTextExtent() on every row
-// of data to determine a column's ideal width, but this one favors
-// speed by setting a presumptive maximum width for each column.
-// Therefore, it treats a personal-name column as having no natural
-// width at all. Its minimum width might be set equal to its header
-// width, but such a refinement is needless in the problem domain. In
-// the most extreme case, all inelastic columns would fit, but there
-// would be not a single pixel available for elastic columns, which
-// would all in effect be dropped; again, in the problem domain, that
-// would actually be preferable to failing to produce any output.
-//
-// Therefore, elastic columns are clipped, and inelastic ones are not.
-// All other column properties are independent, and specified by
-// arguments, but clipping depends on the elasticity argument. It is
-// distinguished only because clipping is a distinct layout operation.
-//
-//  - is_hidden(): Data for every row of all potential columns are
-//    passed into this class; hidden columns are suppressed so that
-//    they don't appear in the output at all.
-//
-//  - is_elastic(): An elastic column has no innate fixed or preferred
-//    width. After all inelastic columns have claimed their required
-//    widths, any remaining width available is prorated among elastic
-//    columns, which therefore may be wider than their widest contents
-//    or narrower than their narrowest. As a consequence, elastic
-//    columns are clipped--vide supra.
-//
-//  - is_clipped(): A clipped column is truncated to fit its allotted
-//    space. Only elastic columns are clipped--vide supra.
-
-class table_column_info
-{
-  public:
-    table_column_info
-        (std::string      const& header
-        ,int                     width
-        ,oenum_h_align    const  alignment
-        ,oenum_visibility const  visibility
-        ,oenum_elasticity const  elasticity
-        )
-        :col_header_ (header)
-        ,col_width_  (width)
-        ,alignment_  (alignment)
-        ,is_hidden_  (oe_hidden  == visibility)
-        ,is_elastic_ (oe_elastic == elasticity)
-        {
-        }
-
-    std::string const& col_header() const {return col_header_;}
-    int                col_width()  const {return col_width_;}
-    oenum_h_align      alignment()  const {return alignment_;}
-    bool               is_hidden()  const {return is_hidden_;}
-    bool               is_elastic() const {return is_elastic_;}
-    bool               is_clipped() const {return is_elastic();}
-
-  private:
-    std::string   const col_header_;
-
-  public:
-    // PDF !! Modified directly by set_column_widths(), hence neither
-    // private nor const.
-    //
-    // Width in pixels. Because the wxPdfDC uses wxMM_POINTS, each
-    // pixel is one point = 1/72 inch.
-    int col_width_;
-
-  private:
-    oenum_h_align const alignment_;
-    bool          const is_hidden_;
-    bool          const is_elastic_;
-};
-
-void set_column_widths
-    (int                             total_width
-    ,int                           & column_margin
-    ,std::vector<table_column_info>& all_columns
-    );
-
 wx_table_generator::wx_table_generator
     (group_quote_style_tag                 // tag not referenced
     ,std::vector<column_parameters> const& vc
@@ -505,211 +416,6 @@ LMI_ASSERT(std::size_t(h / lh) == 1u + 
count_newlines(z.header));
         );
 }
 
-/// Compute column widths.
-///
-/// First, allocate adequate width to each inelastic column; then
-/// distribute any excess width left over among elastic columns.
-///
-/// The width of each inelastic column reflects:
-///  - a mask like "999,999" (ideally, there would instead be a
-///    quasi-global data structure mapping symbolic column names
-///    to their corresponding headers and maximal widths)
-///  - the header width
-///  - PDF !! the bilateral margins added as a first step below
-/// The margins may be slightly reduced by this function to make
-/// everything fit when it otherwise wouldn't.
-
-void set_column_widths
-    (int                             total_width
-    ,int                           & column_margin
-    ,std::vector<table_column_info>& all_columns
-    )
-//
-// const    total_width    max table width (page width - page margins)
-// mutable  column_margin  spacing on both left and right of column
-// mutable  all_columns    std::vector<table_column_info>
-//   table_column_info::col_width_ is the only member changed
-{
-    // PDF !! Unconditionally add bilateral margins even though they
-    // may conditionally be removed below. This is a questionable
-    // design decision; if it is later reversed, then remove the
-    // comment about it above the implementation.
-    for(auto& i : all_columns)
-        {
-        if(!i.is_hidden() && !i.is_elastic())
-            {
-            i.col_width_ += 2 * column_margin;
-            }
-        }
-
-    // Number of non-hidden columns.
-    int number_of_columns = 0;
-
-    // Number of non-hidden elastic columns.
-    int number_of_elastic_columns = 0;
-
-    // Total width of all non-hidden inelastic columns.
-    int total_inelastic_width = 0;
-
-    for(auto const& i : all_columns)
-        {
-        if(i.is_hidden())
-            {
-            continue;
-            }
-
-        ++number_of_columns;
-
-        if(i.is_elastic())
-            {
-            ++number_of_elastic_columns;
-            }
-        else
-            {
-            total_inelastic_width += i.col_width();
-            }
-        }
-
-    if(total_width < total_inelastic_width)
-        {
-        // The inelastic columns don't all fit with their original
-        // one-em presumptive bilateral margins. Try to make them fit
-        // by reducing the margins slightly.
-        //
-        // The number of pixels that would need to be removed is:
-        auto const overflow = total_inelastic_width - total_width;
-
-        // Because inelastic columns take more than the available
-        // horizontal space, there's no room to fit any elastic
-        // columns, so the column-fitting problem is overconstrained.
-        // Therefore, don't even try reducing margins if there are any
-        // elastic columns.
-        if(!number_of_elastic_columns)
-            {
-// Also calculate the number of pixels by which it overflows for each column
-            // We need to round up in division here to be sure that all columns
-            // fit into the available width.
-            auto const overflow_per_column = outward_quotient
-                (overflow
-                ,number_of_columns
-                );
-// Now determine whether reducing the margins will make the table fit.
-// If that works, then do it; else don't do it, and print a warning.
-//
-// column_margin is the padding on each side of every column, so
-// the number of pixels between columns, as the table was originally
-// laid out, is two times column_margin--which, as we just determined,
-// was too generous, so we're going to try reducing it.
-// Then this conditional compares
-//   the number of pixels by which we must shrink each column, to
-//   the number of pixels of padding between columns
-// Reducing the padding is a workable strategy if the desired reduction
-// is less than the padding.
-//
-// Is this as good as it can be, given that coordinates are integers?
-// Answer: Yes--the integers count points, not ems or characters, and
-// typographers wouldn't use any finer unit for this task.
-            if(overflow_per_column <= 2 * column_margin)
-                {
-                // We are going to reduce the total width by more than
-                // necessary, in general, because of rounding up above, so
-                // compensate for it by giving 1 extra pixel until we run out
-                // of these "underflow" pixels.
-// Defect: the number of pixels separating columns might now be zero.
-// '9' is five PDF pixels wide; do we need, say, two pixels between columns?
-//
-// Suggestion: change the
-//   overflow_per_column <= column_margin
-// condition to something like:
-//    overflow_per_column <= column_margin - 4 // two pixels on each side
-//    overflow_per_column <= column_margin - 2 // one pixel on each side
-                auto underflow = overflow_per_column * number_of_columns - 
overflow;
-
-                for(auto& i : all_columns)
-                    {
-                    if(i.is_hidden())
-                        {
-                        continue;
-                        }
-
-                    i.col_width_ -= overflow_per_column;
-
-                    if(0 < underflow)
-                        {
-                        ++i.col_width_;
-                        --underflow;
-                        }
-                    }
-
-                column_margin -= (overflow_per_column + 1) / 2;
-
-                // We condensed the columns enough to make them fit, so no need
-                // for the warning and we don't have any elastic columns, so
-                // we're done.
-                return;
-                }
-// If overflow_per_column is 1, then column_margin -= 1
-// "           "          "  2,   "        "           1
-// "           "          "  3,   "        "           2
-// "           "          "  4,   "        "           2
-// The 'underflow' logic shrinks columns by the exact number of pixels
-// to use up all the available width. But the column_margin reduction
-// isn't exact due to truncation: when the margin is added (on both sides),
-// is the total of all (margin+column+margin) widths lower than the maximum,
-// so that this is just a small aesthetic issue, or is it too wide, so that
-// not everything fits?
-//
-// Answer:
-// This is an issue of aligning the column text, not of fitting, because the
-// margin is used when positioning the text inside the column width. And the
-// width is correct, so the worst that can happen here is that the text is
-// offset by 0.5 pixels -- but, of course, if we rounded it down, it would be
-// offset by 0.5 pixels in the other direction. So maybe we should write
-//
-//     column_margin -= overflow_per_column / 2;
-//
-// just because it's shorter and not necessarily worse (nor better).
-            }
-
-        warning()
-            << "Not enough space for all " << number_of_columns << " columns."
-            << "\nPrintable width is " << total_width << " points."
-            << "\nData alone require " << total_inelastic_width - 2 * 
column_margin * number_of_columns
-            << " points without any margins for legibility."
-            << "\nColumn margins of " << column_margin << " points on both 
sides"
-            << " would take up " << 2 * column_margin * number_of_columns << " 
additional points."
-            << LMI_FLUSH
-            ;
-        return;
-        }
-
-    // Lay out elastic columns in whatever space is left over after
-    // accounting for all inelastic columns. Clip to make them fit.
-    //
-    // If there's more than enough space for them, then expand them
-    // to consume all available space.
-    if(number_of_elastic_columns)
-        {
-        int const width_of_each_elastic_column = outward_quotient
-            (total_width - total_inelastic_width
-            ,number_of_elastic_columns
-            );
-
-        for(auto& i : all_columns)
-            {
-            if(i.is_hidden())
-                {
-                continue;
-                }
-
-            if(i.is_elastic())
-                {
-                i.col_width_ = width_of_each_elastic_column;
-                }
-            }
-        }
-}
-
 void wx_table_generator::do_output_single_row
     (int&                            pos_x
     ,int&                            pos_y
diff --git a/wx_table_generator.hpp b/wx_table_generator.hpp
index af79c07..de075ed 100644
--- a/wx_table_generator.hpp
+++ b/wx_table_generator.hpp
@@ -25,6 +25,7 @@
 #include "config.hpp"
 
 #include "oecumenic_enumerations.hpp"
+#include "report_table.hpp"             // table_column_info
 
 #include <wx/dc.h>
 #include <wx/font.h>
@@ -33,8 +34,6 @@
 #include <string>
 #include <vector>
 
-class table_column_info;
-
 /// Aggregate of per-column table-generator ctor arguments.
 
 struct column_parameters



reply via email to

[Prev in Thread] Current Thread [Next in Thread]