lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] gwc-no-xslfo 4fcbd32 03/12: Import 'wx_table_generat


From: Greg Chicares
Subject: [lmi-commits] [lmi] gwc-no-xslfo 4fcbd32 03/12: Import 'wx_table_generator.?pp' changes verbatim from vz-no-xslfo
Date: Sat, 27 Jan 2018 04:23:33 -0500 (EST)

branch: gwc-no-xslfo
commit 4fcbd3234f1cf592fada52b517de8ab94a7a0387
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Import 'wx_table_generator.?pp' changes verbatim from vz-no-xslfo
---
 wx_table_generator.cpp | 168 +++++++++++++++++++++++++++++++++++++++++++------
 wx_table_generator.hpp |  59 ++++++++++++++---
 2 files changed, 199 insertions(+), 28 deletions(-)

diff --git a/wx_table_generator.cpp b/wx_table_generator.cpp
index 28f8c28..79d57f3 100644
--- a/wx_table_generator.cpp
+++ b/wx_table_generator.cpp
@@ -53,6 +53,7 @@ wx_table_generator::wx_table_generator
     ,total_width_(total_width)
     ,char_height_(dc_.GetCharHeight())
     ,row_height_((4 * char_height_ + 2) / 3) // Arbitrarily use 1.333 line 
spacing.
+    ,column_margin_(dc_.GetTextExtent("M").x)
     ,has_column_widths_(false)
     ,max_header_lines_(1)
 {
@@ -64,6 +65,18 @@ wx_table_generator::wx_table_generator
     dc_.SetPen(pen);
 }
 
+void wx_table_generator::use_condensed_style()
+{
+    row_height_ = char_height_;
+    draw_separators_ = false;
+    use_bold_headers_ = false;
+}
+
+void wx_table_generator::align_right()
+{
+    align_right_ = true;
+}
+
 void wx_table_generator::add_column
     (std::string const& header
     ,std::string const& widest_text
@@ -77,7 +90,11 @@ void wx_table_generator::add_column
         }
     else
         {
-        wxDCFontChanger set_header_font(dc_, get_header_font());
+        wxDCFontChanger set_header_font(dc_);
+        if(use_bold_headers_)
+            {
+            set_header_font.Set(get_header_font());
+            }
 
         // Set width to the special value of 0 for the variable width columns.
         width = widest_text.empty() ? 0 : dc_.GetTextExtent(widest_text).x;
@@ -94,8 +111,7 @@ void wx_table_generator::add_column
             {
             increase_to_if_smaller(width, 
dc_.GetMultiLineTextExtent(header).x);
 
-            // Add roughly 1 em margins on both sides.
-            width += dc_.GetTextExtent("MM").x;
+            width += 2*column_margin_;
             }
         }
 
@@ -157,6 +173,8 @@ void 
wx_table_generator::do_compute_column_widths_if_necessary()
         return;
         }
 
+    has_column_widths_ = true;
+
     int num_expand = 0;
     int total_fixed = 0;
 
@@ -179,7 +197,43 @@ void 
wx_table_generator::do_compute_column_widths_if_necessary()
 
     if(total_width_ < total_fixed)
         {
-        warning() << "Not enough space for all fixed columns." << LMI_FLUSH;
+        auto const overflow = total_fixed - total_width_;
+
+        // If we have only fixed columns, try to make them fit by decreasing
+        // the margins around them if this can help, assuming that we can
+        // reduce them by up to half if really needed.
+        if(!num_expand)
+            {
+            int const num_columns = columns_.size();
+            auto const overflow_per_column =
+                (overflow + num_columns - 1)/num_columns;
+            if(overflow_per_column <= column_margin_)
+                {
+                for(auto& i : columns_)
+                    {
+                    if(i.is_hidden())
+                        {
+                        continue;
+                        }
+
+                    i.width_ -= overflow_per_column;
+                    }
+
+                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 expanding columns, so
+                // we're done.
+                return;
+                }
+            }
+
+        warning()
+            << "Not enough space for all fixed columns: "
+            << overflow
+            << " more pixels needed."
+            << LMI_FLUSH
+            ;
         return;
         }
 
@@ -201,8 +255,6 @@ void 
wx_table_generator::do_compute_column_widths_if_necessary()
                 }
             }
         }
-
-    has_column_widths_ = true;
 }
 
 void wx_table_generator::do_output_values
@@ -216,7 +268,10 @@ void wx_table_generator::do_output_values
     int const y_text = y + char_height_;
     y += row_height_;
 
-    do_output_vert_separator(x, y_top, y);
+    if(draw_separators_)
+        {
+        do_output_vert_separator(x, y_top, y);
+        }
 
     std::size_t const num_columns = columns_.size();
     for(std::size_t col = 0; col < num_columns; ++col)
@@ -233,21 +288,31 @@ void wx_table_generator::do_output_values
         if(!s.empty())
             {
             int x_text = x;
-            if(ci.is_centered_)
+
+            if(align_right_)
                 {
-                // Centre the text for the columns configured to do it.
-                x_text += (width - dc_.GetTextExtent(s).x) / 2;
+                x_text += width - dc_.GetTextExtent(s).x;
                 }
             else
                 {
-                // Otherwise just offset it by ~1 em.
-                x_text += dc_.GetTextExtent("M").x;
-                }
+                if(ci.is_centered_)
+                    {
+                    // Centre the text for the columns configured to do it.
+                    x_text += (width - dc_.GetTextExtent(s).x) / 2;
+                    }
+                else
+                    {
+                    x_text += column_margin_;
+                    }
+            }
 
             dc_.DrawText(s, x_text, y_text);
             }
         x += width;
-        do_output_vert_separator(x, y_top, y);
+        if(draw_separators_)
+            {
+            do_output_vert_separator(x, y_top, y);
+            }
         }
 }
 
@@ -269,8 +334,17 @@ void wx_table_generator::output_horz_separator
     (std::size_t begin_column
     ,std::size_t end_column
     ,int y
+    ,enum_output_mode output_mode
     )
 {
+    switch(output_mode)
+        {
+        case e_output_normal:
+            break;
+        case e_output_measure_only:
+            return;
+        }
+
     LMI_ASSERT(begin_column < end_column);
     LMI_ASSERT(end_column <= columns_.size());
 
@@ -287,11 +361,24 @@ void wx_table_generator::output_horz_separator
     do_output_horz_separator(x1, x2, y);
 }
 
-void wx_table_generator::output_header(int* pos_y)
+void wx_table_generator::output_header(int* pos_y, enum_output_mode 
output_mode)
 {
+    switch(output_mode)
+        {
+        case e_output_normal:
+            break;
+        case e_output_measure_only:
+            *pos_y += max_header_lines_ * row_height_;
+            return;
+        }
+
     do_compute_column_widths_if_necessary();
 
-    wxDCFontChanger set_header_font(dc_, get_header_font());
+    wxDCFontChanger set_header_font(dc_);
+    if(use_bold_headers_)
+        {
+        set_header_font.Set(get_header_font());
+        }
 
     // Split headers in single lines and fill up the entire columns*lines 2D
     // matrix, using empty strings for the headers with less than the maximal
@@ -328,9 +415,47 @@ void wx_table_generator::output_header(int* pos_y)
         }
 
     // Finally draw the separators above and (a double one) below them.
-    do_output_horz_separator(left_margin_, x,  y_top    );
-    do_output_horz_separator(left_margin_, x, *pos_y - 1);
-    do_output_horz_separator(left_margin_, x, *pos_y    );
+    if(draw_separators_)
+        {
+        do_output_horz_separator(left_margin_, x,  y_top    );
+        do_output_horz_separator(left_margin_, x, *pos_y - 1);
+        do_output_horz_separator(left_margin_, x, *pos_y    );
+        }
+}
+
+void wx_table_generator::output_super_header
+        (std::string const& header
+        ,std::size_t        begin_column
+        ,std::size_t        end_column
+        ,int*               pos_y
+        ,enum_output_mode   output_mode
+        )
+{
+    std::vector<std::string> const lines(split_into_lines(header));
+
+    switch(output_mode)
+        {
+        case e_output_normal:
+            break;
+        case e_output_measure_only:
+            *pos_y += row_height_*lines.size();
+            return;
+        }
+
+    // We don't have a function for getting the rectangle of a span of columns,
+    // but we can reuse the existing text_rect() if we just increase its width
+    // by the width of all the extra (i.e. not counting the starting one)
+    // columns in this span.
+    auto rect = text_rect(begin_column, *pos_y);
+    rect.width += do_get_cell_x(end_column) - do_get_cell_x(begin_column + 1);
+
+    for(auto const& line : lines)
+        {
+        dc_.DrawLabel(line, rect, wxALIGN_CENTER_HORIZONTAL);
+
+        rect.y += row_height_;
+        *pos_y += row_height_;
+        }
 }
 
 void wx_table_generator::output_row
@@ -341,7 +466,10 @@ void wx_table_generator::output_row
     int x = left_margin_;
     do_output_values(x, *pos_y, values);
 
-    do_output_horz_separator(left_margin_, x, *pos_y);
+    if(draw_separators_)
+        {
+        do_output_horz_separator(left_margin_, x, *pos_y);
+        }
 }
 
 void wx_table_generator::output_highlighted_cell
diff --git a/wx_table_generator.hpp b/wx_table_generator.hpp
index 3e3f657..1ba0e58 100644
--- a/wx_table_generator.hpp
+++ b/wx_table_generator.hpp
@@ -24,6 +24,8 @@
 
 #include "config.hpp"
 
+#include "output_mode.hpp"
+
 #include <wx/dc.h>
 #include <wx/font.h>
 
@@ -52,19 +54,34 @@ class wx_table_generator
     // Adds a column to the table. The total number of added columns determines
     // the number of the expected value in output_row() calls.
     //
-    // Providing an empty header suppresses the table display, while still
-    // taking into account in output_row(), providing a convenient way to hide
-    // a single column without changing the data representation.
+    // Providing an empty header suppresses the column display, while still
+    // taking it into account in output_row(), providing a convenient way to
+    // hide a single column without changing the data representation.
     //
     // Each column must either have a fixed width, specified as the width of
     // the longest text that may appear in this column, or be expandable
     // meaning that the rest of the page width is allocated to it which will be
     // the case if widest_text is empty.
+    //
     // Notice that column headers may be multiline strings.
     void add_column(std::string const& header, std::string const& widest_text);
 
     // Render the headers at the given position and update it.
-    void output_header(int* pos_y);
+    void output_header
+        (int*             pos_y
+        ,enum_output_mode output_mode = e_output_normal
+        );
+
+    // Render a super-header, i.e. a header spanning over several columns. The
+    // columns range is specified as a close/open interval, as usual in C++.
+    // The header string may be multiline, just as with normal headers.
+    void output_super_header
+        (std::string const& header
+        ,std::size_t        begin_column
+        ,std::size_t        end_column
+        ,int*               pos_y
+        ,enum_output_mode   output_mode = e_output_normal
+        );
 
     // Render a row with the given values at the given position and update it.
     // The values here can be single-line only and there must be exactly the
@@ -79,6 +96,9 @@ class wx_table_generator
         ,std::string const& value
         );
 
+    // Return the number of columns.
+    std::size_t columns_count() const {return columns_.size();}
+
     // Return the height of a single table row.
     int row_height() const {return row_height_;}
 
@@ -94,9 +114,10 @@ class wx_table_generator
     // Output a horizontal separator line across the specified columns,
     // using the usual C++ close/open interval convention.
     void output_horz_separator
-        (std::size_t begin_column
-        ,std::size_t end_column
-        ,int         y
+        (std::size_t      begin_column
+        ,std::size_t      end_column
+        ,int              y
+        ,enum_output_mode output_mode = e_output_normal
         );
 
     // Output a vertical separator line before the given column. Notice that
@@ -104,6 +125,15 @@ class wx_table_generator
     // output a separator after the last column.
     void output_vert_separator(std::size_t before_column, int y);
 
+    // Use condensed style: don't draw separators between rows and make them
+    // smaller.
+    void use_condensed_style();
+
+    // By default, columns are centered if they have fixed size or left-aligned
+    // otherwise. By calling this method, this alignment auto-detection is
+    // turned off and all columns are right-aligned.
+    void align_right();
+
   private:
     // Return the font used for the headers.
     wxFont get_header_font() const;
@@ -128,7 +158,8 @@ class wx_table_generator
 
     // These values could be recomputed, but cache them for performance.
     int const char_height_;
-    int const row_height_;
+    int row_height_;
+    int column_margin_;
 
     struct column_info
     {
@@ -160,6 +191,18 @@ class wx_table_generator
     // Maximal number of lines in any column header, initially 1 but can be
     // higher if multiline headers are used.
     std::size_t max_header_lines_;
+
+    // If false, separator lines are not drawn automatically (they can still be
+    // drawn by calling output_horz_separator() or output_vert_separator()
+    // explicitly).
+    bool draw_separators_ = true;
+
+    // If true, headers are drawn in bold.
+    bool use_bold_headers_ = true;
+
+    // If true, force right alignment for all columns instead of centering them
+    // automatically if they have fixed size.
+    bool align_right_ = false;
 };
 
 #endif // wx_table_generator_hpp



reply via email to

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