ruport 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +55 -9
- data/Rakefile +3 -5
- data/examples/line_plotter.rb +3 -0
- data/examples/pdf_complex_report.rb +0 -1
- data/examples/pdf_report_with_common_base.rb +72 -0
- data/examples/pdf_styles.rb +16 -0
- data/examples/simple_pdf_lines.rb +0 -1
- data/lib/ruport.rb +5 -66
- data/lib/ruport/acts_as_reportable.rb +122 -51
- data/lib/ruport/data/grouping.rb +30 -13
- data/lib/ruport/data/record.rb +26 -25
- data/lib/ruport/data/table.rb +91 -34
- data/lib/ruport/formatter.rb +86 -11
- data/lib/ruport/formatter/csv.rb +29 -2
- data/lib/ruport/formatter/html.rb +23 -1
- data/lib/ruport/formatter/pdf.rb +123 -32
- data/lib/ruport/formatter/text.rb +62 -6
- data/lib/ruport/query.rb +75 -39
- data/lib/ruport/renderer.rb +250 -35
- data/lib/ruport/renderer/grouping.rb +2 -2
- data/test/html_formatter_test.rb +4 -1
- data/test/pdf_formatter_test.rb +30 -7
- data/test/query_test.rb +12 -0
- data/test/renderer_test.rb +33 -2
- data/test/table_test.rb +8 -2
- data/test/text_formatter_test.rb +11 -1
- metadata +53 -107
- data/bin/rope +0 -12
- data/examples/rope_examples/itunes/README +0 -12
- data/examples/rope_examples/itunes/Rakefile +0 -39
- data/examples/rope_examples/itunes/config/environment.rb +0 -4
- data/examples/rope_examples/itunes/data/mix.txt +0 -1
- data/examples/rope_examples/itunes/lib/helpers.rb +0 -0
- data/examples/rope_examples/itunes/lib/init.rb +0 -39
- data/examples/rope_examples/itunes/lib/reports.rb +0 -1
- data/examples/rope_examples/itunes/lib/reports/playlist.rb +0 -17
- data/examples/rope_examples/itunes/log/ruport.log +0 -1
- data/examples/rope_examples/itunes/test/test_playlist.rb +0 -8
- data/examples/rope_examples/itunes/util/build +0 -96
- data/examples/rope_examples/itunes/util/sql_exec +0 -5
- data/examples/rope_examples/sales_report/README +0 -4
- data/examples/rope_examples/sales_report/Rakefile +0 -39
- data/examples/rope_examples/sales_report/config/environment.rb +0 -4
- data/examples/rope_examples/sales_report/lib/helpers.rb +0 -0
- data/examples/rope_examples/sales_report/lib/init.rb +0 -39
- data/examples/rope_examples/sales_report/lib/reports.rb +0 -1
- data/examples/rope_examples/sales_report/lib/reports/sales.rb +0 -132
- data/examples/rope_examples/sales_report/log/ruport.log +0 -1
- data/examples/rope_examples/sales_report/output/books.pdf +0 -170
- data/examples/rope_examples/sales_report/output/books.txt +0 -11
- data/examples/rope_examples/sales_report/test/test_sales.rb +0 -8
- data/examples/rope_examples/sales_report/util/build +0 -96
- data/examples/rope_examples/sales_report/util/sql_exec +0 -5
- data/examples/sample.rb +0 -16
- data/lib/ruport/generator.rb +0 -294
- data/lib/ruport/report.rb +0 -262
- data/setup.rb +0 -1585
- data/test/report_test.rb +0 -218
- data/test/samples/foo.rtxt +0 -3
    
        data/lib/ruport/formatter.rb
    CHANGED
    
    | @@ -1,14 +1,70 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # Ruport : Extensible Reporting System                                
         | 
| 2 2 | 
             
            #
         | 
| 3 | 
            -
            #  | 
| 3 | 
            +
            # formatter.rb provides a generalized base class for creating ruport formatters.
         | 
| 4 | 
            +
            #     
         | 
| 5 | 
            +
            # Created By Gregory Brown
         | 
| 6 | 
            +
            # Copyright (C) December 2006, All Rights Reserved.   
         | 
| 4 7 | 
             
            #
         | 
| 5 | 
            -
            # This is free software | 
| 6 | 
            -
             | 
| 7 | 
            -
            module Ruport
         | 
| 8 | 
            +
            # This is free software distributed under the same terms as Ruby 1.8
         | 
| 9 | 
            +
            # See LICENSE and COPYING for details.
         | 
| 10 | 
            +
            module Ruport    
         | 
| 11 | 
            +
              # Formatter is the base class for Ruport's format implementations.
         | 
| 12 | 
            +
              #
         | 
| 13 | 
            +
              # Typically, a Formatter will implement one or more output types,
         | 
| 14 | 
            +
              # and be registered with one or more Renderer classes. 
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              # This class provides all the necessary base functionality to make
         | 
| 17 | 
            +
              # use of Ruport's rendering system, including option handling, data
         | 
| 18 | 
            +
              # access, and basic output wrapping.
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              # The following example should provide a general idea of how formatters
         | 
| 21 | 
            +
              # work, but see the built in formatters for reference implementations. 
         | 
| 22 | 
            +
              # 
         | 
| 23 | 
            +
              # A simple Renderer definition is included to help show the example in
         | 
| 24 | 
            +
              # context, but you can also build your own custom interface to formatter
         | 
| 25 | 
            +
              # if you wish.
         | 
| 26 | 
            +
              #
         | 
| 27 | 
            +
              #   class ReverseRenderer < Ruport::Renderer
         | 
| 28 | 
            +
              #      stage :reversed_header, :reversed_body 
         | 
| 29 | 
            +
              #      option :header_text
         | 
| 30 | 
            +
              #   end
         | 
| 31 | 
            +
              #                                            
         | 
| 32 | 
            +
              #   class ReversedText < Ruport::Formatter 
         | 
| 33 | 
            +
              #      
         | 
| 34 | 
            +
              #      # Hooks formatter up to renderer
         | 
| 35 | 
            +
              #      renders :txt, :for => ReverseRenderer      
         | 
| 36 | 
            +
              #      
         | 
| 37 | 
            +
              #      # Implements ReverseRenderer's :reversed_header hook
         | 
| 38 | 
            +
              #      # but can be used by any renderer   
         | 
| 39 | 
            +
              #      def build_reversed_header   
         | 
| 40 | 
            +
              #         output << "#{options.header_text}\n"
         | 
| 41 | 
            +
              #         output << "The reversed text will follow\n"
         | 
| 42 | 
            +
              #      end  
         | 
| 43 | 
            +
              # 
         | 
| 44 | 
            +
              #      # Implements ReverseRenderer's :reversed_body hook
         | 
| 45 | 
            +
              #      # but can be used by any renderer
         | 
| 46 | 
            +
              #      def build_reversed_body
         | 
| 47 | 
            +
              #         output << data.reverse << "\n"
         | 
| 48 | 
            +
              #      end         
         | 
| 49 | 
            +
              #
         | 
| 50 | 
            +
              #   end    
         | 
| 51 | 
            +
              #
         | 
| 52 | 
            +
              #   puts ReverseRenderer.render_txt(:data => "apple",
         | 
| 53 | 
            +
              #                                   :header_text => "Hello Mike, Hello Joe!")
         | 
| 54 | 
            +
              #   
         | 
| 55 | 
            +
              #   -----
         | 
| 56 | 
            +
              #   OUTPUT: 
         | 
| 57 | 
            +
              # 
         | 
| 58 | 
            +
              #   Hello Mike, Hello Joe!
         | 
| 59 | 
            +
              #   The reversed text will follow
         | 
| 60 | 
            +
              #   elppa
         | 
| 61 | 
            +
              #   
         | 
| 8 62 | 
             
              class Formatter
         | 
| 9 | 
            -
             | 
| 63 | 
            +
                 
         | 
| 64 | 
            +
                # Provides shortcuts so that you can use Ruport's default rendering
         | 
| 65 | 
            +
                # capabilities within your custom formatters   
         | 
| 66 | 
            +
                #
         | 
| 10 67 | 
             
                module RenderingTools
         | 
| 11 | 
            -
             | 
| 12 68 | 
             
                  # Iterates through <tt>data</tt> and passes
         | 
| 13 69 | 
             
                  # each row to render_row with the given options
         | 
| 14 70 | 
             
                  def render_data_by_row(options={},&block)
         | 
| @@ -75,9 +131,15 @@ module Ruport | |
| 75 131 | 
             
                end
         | 
| 76 132 |  | 
| 77 133 | 
             
                include RenderingTools
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                 | 
| 80 | 
            -
                attr_accessor : | 
| 134 | 
            +
               
         | 
| 135 | 
            +
                # Set by the <tt>:data</tt> attribute from Renderer#render
         | 
| 136 | 
            +
                attr_accessor :data              
         | 
| 137 | 
            +
                
         | 
| 138 | 
            +
                # Set automatically by Renderer#render(format) or Renderer#render_format
         | 
| 139 | 
            +
                attr_accessor :format                                                    
         | 
| 140 | 
            +
                
         | 
| 141 | 
            +
                # Set automatically by Renderer#render as a Renderer::Options option built
         | 
| 142 | 
            +
                # by the hash provided.
         | 
| 81 143 | 
             
                attr_writer :options
         | 
| 82 144 |  | 
| 83 145 | 
             
                # Registers the formatter with one or more Renderers
         | 
| @@ -116,7 +178,7 @@ module Ruport | |
| 116 178 | 
             
                  @output ||= ""
         | 
| 117 179 | 
             
                end
         | 
| 118 180 |  | 
| 119 | 
            -
                # Provides a  | 
| 181 | 
            +
                # Provides a Renderer::Options object for storing formatting options
         | 
| 120 182 | 
             
                def options
         | 
| 121 183 | 
             
                  @options ||= Renderer::Options.new
         | 
| 122 184 | 
             
                end 
         | 
| @@ -124,6 +186,19 @@ module Ruport | |
| 124 186 | 
             
                # Clears output.
         | 
| 125 187 | 
             
                def clear_output
         | 
| 126 188 | 
             
                  @output.replace("")
         | 
| 189 | 
            +
                end   
         | 
| 190 | 
            +
                
         | 
| 191 | 
            +
                # Evaluates the string using ERB and returns the results.
         | 
| 192 | 
            +
                #
         | 
| 193 | 
            +
                # If <tt>:binding</tt> is specified, it will evaluate the template
         | 
| 194 | 
            +
                # in that context.
         | 
| 195 | 
            +
                def erb(string,options={})      
         | 
| 196 | 
            +
                  require "erb"
         | 
| 197 | 
            +
                  if string =~ /\.r\w+$/
         | 
| 198 | 
            +
                    ERB.new(File.read(string)).result(options[:binding]||binding)
         | 
| 199 | 
            +
                  else
         | 
| 200 | 
            +
                    ERB.new(string).result(options[:binding]||binding)
         | 
| 201 | 
            +
                  end
         | 
| 127 202 | 
             
                end
         | 
| 128 203 |  | 
| 129 204 | 
             
                # Provides a shortcut for per format handlers.
         | 
    
        data/lib/ruport/formatter/csv.rb
    CHANGED
    
    | @@ -1,6 +1,32 @@ | |
| 1 | 
            +
            # Ruport : Extensible Reporting System                                
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # formatter/csv.rb provides csv formatting for Ruport.
         | 
| 4 | 
            +
            #     
         | 
| 5 | 
            +
            # Original code dates back to the earliest versions of Ruport in August 2005
         | 
| 6 | 
            +
            # Extended over time, with much of the existing code being added around
         | 
| 7 | 
            +
            # December 2006.
         | 
| 8 | 
            +
            #    
         | 
| 9 | 
            +
            # Copyright (C) 2005-2007 Gregory Brown, All Rights Reserved.  
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # This is free software distributed under the same terms as Ruby 1.8
         | 
| 12 | 
            +
            # See LICENSE and COPYING for details.   
         | 
| 13 | 
            +
            #
         | 
| 1 14 | 
             
            module Ruport
         | 
| 2 15 |  | 
| 3 | 
            -
              # This formatter implements the CSV format for  | 
| 16 | 
            +
              # This formatter implements the CSV format for Ruport's Row, Table, Group
         | 
| 17 | 
            +
              # and Grouping renderers.  It is a light wrapper around James Edward Gray II's
         | 
| 18 | 
            +
              # FasterCSV.
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              # === Rendering Options
         | 
| 21 | 
            +
              #                                                     
         | 
| 22 | 
            +
              # <tt>:style</tt> Used for grouping (:inline,:justified,:raw)      
         | 
| 23 | 
            +
              #
         | 
| 24 | 
            +
              # <tt>:format_options</tt> A hash of FasterCSV options  
         | 
| 25 | 
            +
              #
         | 
| 26 | 
            +
              # <tt>:show_table_headers</tt> True by default
         | 
| 27 | 
            +
              #
         | 
| 28 | 
            +
              # <tt>:show_group_headers</tt> True by default
         | 
| 29 | 
            +
              #
         | 
| 4 30 | 
             
              class Formatter::CSV < Formatter
         | 
| 5 31 |  | 
| 6 32 | 
             
                renders :csv, :for => [ Renderer::Row,   Renderer::Table, 
         | 
| @@ -55,7 +81,8 @@ module Ruport | |
| 55 81 | 
             
                    output << "#{data.grouped_by}," << grouping_columns
         | 
| 56 82 | 
             
                  end
         | 
| 57 83 | 
             
                end
         | 
| 58 | 
            -
             | 
| 84 | 
            +
               
         | 
| 85 | 
            +
                # determines the proper style to use and renders the Grouping.
         | 
| 59 86 | 
             
                def build_grouping_body
         | 
| 60 87 | 
             
                  case style
         | 
| 61 88 | 
             
                  when :inline
         | 
| @@ -1,5 +1,25 @@ | |
| 1 | 
            +
            # Ruport : Extensible Reporting System                                
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # formatter/html.rb provides html formatting for Ruport.
         | 
| 4 | 
            +
            #     
         | 
| 5 | 
            +
            # Created by Gregory Brown, late 2005.  Updated numerous times as needed to 
         | 
| 6 | 
            +
            # fit new formatting systems.
         | 
| 7 | 
            +
            #    
         | 
| 8 | 
            +
            # Copyright (C) 2005-2007 Gregory Brown, All Rights Reserved.  
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
            # This is free software distributed under the same terms as Ruby 1.8
         | 
| 11 | 
            +
            # See LICENSE and COPYING for details.   
         | 
| 12 | 
            +
            #
         | 
| 1 13 | 
             
            module Ruport
         | 
| 2 | 
            -
              #  | 
| 14 | 
            +
              # This class produces HTML output for Ruport's Row,Table,Group, and Grouping
         | 
| 15 | 
            +
              # renderers.  It can be used as a subclass, as it has some helper methods
         | 
| 16 | 
            +
              # that might be useful for custom output
         | 
| 17 | 
            +
              #
         | 
| 18 | 
            +
              # === Rendering Options
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              # <tt>:show_table_headers</tt>  True by default   
         | 
| 21 | 
            +
              #
         | 
| 22 | 
            +
              # <tt>:show_group_headers</tt>  True by default   
         | 
| 3 23 | 
             
              #
         | 
| 4 24 | 
             
              class Formatter::HTML < Formatter    
         | 
| 5 25 |  | 
| @@ -21,6 +41,8 @@ module Ruport | |
| 21 41 | 
             
                  end
         | 
| 22 42 | 
             
                end
         | 
| 23 43 |  | 
| 44 | 
            +
                # Uses the Row renderer to build up the table body.
         | 
| 45 | 
            +
                # Replaces nil and empty strings with " " 
         | 
| 24 46 | 
             
                def build_table_body
         | 
| 25 47 | 
             
                  render_data_by_row do |rend|
         | 
| 26 48 | 
             
                    r = rend.data
         | 
    
        data/lib/ruport/formatter/pdf.rb
    CHANGED
    
    | @@ -1,19 +1,43 @@ | |
| 1 | 
            +
            # Ruport : Extensible Reporting System                                
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # formatter/pdf.rb provides text formatting for Ruport.
         | 
| 4 | 
            +
            #     
         | 
| 5 | 
            +
            # Created by Gregory Brown, February 2006     
         | 
| 6 | 
            +
            # Extended by James Healy, Fall 2006
         | 
| 7 | 
            +
            # Copyright (C) 2006-2007 Gregory Brown / James Healy, All Rights Reserved.  
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # Initially inspired by some ideas and code from Simon Claret,
         | 
| 10 | 
            +
            # with many improvements from James Healy and Michael Milner over time.
         | 
| 11 | 
            +
            #
         | 
| 12 | 
            +
            # This is free software distributed under the same terms as Ruby 1.8
         | 
| 13 | 
            +
            # See LICENSE and COPYING for details.   
         | 
| 14 | 
            +
            #
         | 
| 1 15 | 
             
            module Ruport
         | 
| 2 16 |  | 
| 3 | 
            -
              # PDF  | 
| 17 | 
            +
              # This class provides PDF output for Ruport's Table, Group, and Grouping
         | 
| 18 | 
            +
              # renderers.  It wraps Austin Ziegler's PDF::Writer to provide a higher
         | 
| 19 | 
            +
              # level interface and provides a number of helpers designed to make
         | 
| 20 | 
            +
              # generating PDF reports much easier.  You will typically want to build
         | 
| 21 | 
            +
              # subclasses of this formatter to customize it as needed.
         | 
| 4 22 | 
             
              #
         | 
| 5 | 
            -
              # | 
| 23 | 
            +
              # Many methods forward options to PDF::Writer, so you may wish to consult
         | 
| 24 | 
            +
              # its API docs.
         | 
| 25 | 
            +
              #
         | 
| 26 | 
            +
              # === Rendering Options
         | 
| 6 27 | 
             
              #     General:
         | 
| 7 28 | 
             
              #       * paper_size  #=> "LETTER"
         | 
| 8 29 | 
             
              #       * paper_orientation #=> :portrait
         | 
| 9 30 | 
             
              #
         | 
| 10 31 | 
             
              #     Text:
         | 
| 11 | 
            -
              #       * text_format
         | 
| 32 | 
            +
              #       * text_format (sets options to be passed to add_text by default)  
         | 
| 12 33 | 
             
              #     
         | 
| 13 34 | 
             
              #     Table:
         | 
| 14 35 | 
             
              #       * table_format (a hash that can take any of the options available
         | 
| 15 36 | 
             
              #           to PDF::SimpleTable)
         | 
| 16 | 
            -
              #       * table_format[:maximum_width] #=> 500
         | 
| 37 | 
            +
              #       * table_format[:maximum_width] #=> 500   
         | 
| 38 | 
            +
              #
         | 
| 39 | 
            +
              #     Grouping:
         | 
| 40 | 
            +
              #       * style (:inline,:justified,:separated,:offset)
         | 
| 17 41 | 
             
              #
         | 
| 18 42 | 
             
              class Formatter::PDF < Formatter    
         | 
| 19 43 |  | 
| @@ -21,9 +45,7 @@ module Ruport | |
| 21 45 | 
             
                                        Renderer::Group, Renderer::Grouping ]
         | 
| 22 46 |  | 
| 23 47 | 
             
                attr_writer :pdf_writer
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                attr_accessor :table_footer_proc
         | 
| 26 | 
            -
                
         | 
| 48 | 
            +
             | 
| 27 49 | 
             
                opt_reader  :show_table_headers,
         | 
| 28 50 | 
             
                            :style,
         | 
| 29 51 | 
             
                            :table_format,
         | 
| @@ -40,7 +62,7 @@ module Ruport | |
| 40 62 |  | 
| 41 63 | 
             
                # Returns the current PDF::Writer object or creates a new one if it has not
         | 
| 42 64 | 
             
                # been set yet.
         | 
| 43 | 
            -
                #
         | 
| 65 | 
            +
                #    
         | 
| 44 66 | 
             
                def pdf_writer
         | 
| 45 67 | 
             
                  @pdf_writer ||= options.formatter ||
         | 
| 46 68 | 
             
                    ::PDF::Writer.new( :paper => paper_size || "LETTER",
         | 
| @@ -60,15 +82,19 @@ module Ruport | |
| 60 82 | 
             
                def finalize_table
         | 
| 61 83 | 
             
                  render_pdf unless options.skip_finalize_table
         | 
| 62 84 | 
             
                end
         | 
| 63 | 
            -
             | 
| 85 | 
            +
                
         | 
| 86 | 
            +
                # Generates a header with the group name for Renderer::Group
         | 
| 64 87 | 
             
                def build_group_header
         | 
| 65 88 | 
             
                  pad(10) { add_text data.name.to_s, :justification => :center }
         | 
| 66 89 | 
             
                end
         | 
| 67 | 
            -
             | 
| 90 | 
            +
                
         | 
| 91 | 
            +
                # Renders the group as a table for Renderer::Group
         | 
| 68 92 | 
             
                def build_group_body
         | 
| 69 93 | 
             
                  render_table data, options.to_hash.merge(:formatter => pdf_writer)
         | 
| 70 94 | 
             
                end
         | 
| 71 | 
            -
             | 
| 95 | 
            +
                                 
         | 
| 96 | 
            +
                # Determines which style to use and renders the main body for
         | 
| 97 | 
            +
                # Renderer::Grouping
         | 
| 72 98 | 
             
                def build_grouping_body
         | 
| 73 99 | 
             
                  case style
         | 
| 74 100 | 
             
                  when :inline
         | 
| @@ -82,12 +108,21 @@ module Ruport | |
| 82 108 | 
             
                    raise NotImplementedError, "Unknown style"
         | 
| 83 109 | 
             
                  end
         | 
| 84 110 | 
             
                end
         | 
| 85 | 
            -
             | 
| 111 | 
            +
               
         | 
| 112 | 
            +
                # calls <tt>render_pdf</tt> 
         | 
| 86 113 | 
             
                def finalize_grouping
         | 
| 87 114 | 
             
                  render_pdf
         | 
| 88 115 | 
             
                end
         | 
| 89 116 |  | 
| 90 | 
            -
                # Call PDF::Writer#text with the given arguments
         | 
| 117 | 
            +
                # Call PDF::Writer#text with the given arguments, using <tt>text_format</tt>
         | 
| 118 | 
            +
                # defaults, if they are defined.                                       
         | 
| 119 | 
            +
                #
         | 
| 120 | 
            +
                # Example:
         | 
| 121 | 
            +
                #
         | 
| 122 | 
            +
                #   options.text_format { :font_size => 14 }
         | 
| 123 | 
            +
                #
         | 
| 124 | 
            +
                #   add_text("Hello Joe") #renders at 14pt
         | 
| 125 | 
            +
                #   add_text("Hello Mike",:font_size => 16) # renders at 16pt
         | 
| 91 126 | 
             
                def add_text(text, format_opts={})
         | 
| 92 127 | 
             
                  format_opts = text_format.merge(format_opts) if text_format
         | 
| 93 128 | 
             
                  pdf_writer.text(text, format_opts)
         | 
| @@ -125,7 +160,22 @@ module Ruport | |
| 125 160 | 
             
                  pdf_writer.add_image_from_file(path, x, y, img_width, img_height) 
         | 
| 126 161 | 
             
                end
         | 
| 127 162 |  | 
| 128 | 
            -
                # Draws some text on the canvas, surrounded by a box with rounded  | 
| 163 | 
            +
                # Draws some text on the canvas, surrounded by a box with rounded corner
         | 
| 164 | 
            +
                #
         | 
| 165 | 
            +
                # Yields an OpenStruct which options can be defined on.
         | 
| 166 | 
            +
                # 
         | 
| 167 | 
            +
                # Example:
         | 
| 168 | 
            +
                #
         | 
| 169 | 
            +
                #    rounded_text_box(options.text) do |o|
         | 
| 170 | 
            +
                #      o.radius = 5
         | 
| 171 | 
            +
                #      o.width     = options.width  || 400
         | 
| 172 | 
            +
                #      o.height    = options.height || 130
         | 
| 173 | 
            +
                #      o.font_size = options.font_size || 12
         | 
| 174 | 
            +
                #      o.heading   = options.heading
         | 
| 175 | 
            +
                #   
         | 
| 176 | 
            +
                #      o.x = pdf_writer.absolute_x_middle - o.width/2
         | 
| 177 | 
            +
                #      o.y = 300
         | 
| 178 | 
            +
                #    end
         | 
| 129 179 | 
             
                #
         | 
| 130 180 | 
             
                def rounded_text_box(text)
         | 
| 131 181 | 
             
                  opts = OpenStruct.new
         | 
| @@ -167,34 +217,60 @@ module Ruport | |
| 167 217 | 
             
                    pdf_writer.add_object(wm, :all_pages)
         | 
| 168 218 | 
             
                  end
         | 
| 169 219 | 
             
                end
         | 
| 170 | 
            -
             | 
| 220 | 
            +
                
         | 
| 221 | 
            +
                # adds n to pdf_writer.y, moving the vertical drawing position in the
         | 
| 222 | 
            +
                # document 
         | 
| 171 223 | 
             
                def move_cursor(n) 
         | 
| 172 224 | 
             
                  pdf_writer.y += n
         | 
| 173 225 | 
             
                end
         | 
| 174 | 
            -
             | 
| 226 | 
            +
                
         | 
| 227 | 
            +
                # moves the cursor to a specific y coordinate in the document
         | 
| 175 228 | 
             
                def move_cursor_to(n)
         | 
| 176 229 | 
             
                  pdf_writer.y = n
         | 
| 177 230 | 
             
                end
         | 
| 178 | 
            -
             | 
| 231 | 
            +
                
         | 
| 232 | 
            +
                # puts a specified amount of whitespace above and below the code
         | 
| 233 | 
            +
                # in your block.  For example, if you want to surround the top and
         | 
| 234 | 
            +
                # bottom of a line of text with 5 pixels of whitespace:
         | 
| 235 | 
            +
                #
         | 
| 236 | 
            +
                #    pad(5) { add_text "This will be padded" }
         | 
| 179 237 | 
             
                def pad(y,&block)
         | 
| 180 238 | 
             
                  move_cursor(-y)
         | 
| 181 239 | 
             
                  block.call
         | 
| 182 240 | 
             
                  move_cursor(-y)
         | 
| 183 241 | 
             
                end
         | 
| 184 | 
            -
             | 
| 242 | 
            +
                
         | 
| 243 | 
            +
                # Adds a specified amount of whitespace above the code in your block.  
         | 
| 244 | 
            +
                # For example, if you want to add a 10 pixel buffer to the top of a
         | 
| 245 | 
            +
                # line of text:
         | 
| 246 | 
            +
                #
         | 
| 247 | 
            +
                #    pad_top(10) { add_text "This will be padded on top" }
         | 
| 185 248 | 
             
                def pad_top(y,&block)
         | 
| 186 249 | 
             
                  move_cursor(-y)
         | 
| 187 250 | 
             
                  block.call
         | 
| 188 251 | 
             
                end
         | 
| 189 | 
            -
             | 
| 252 | 
            +
                
         | 
| 253 | 
            +
                # Adds a specified amount of whitespace below the code in your block.  
         | 
| 254 | 
            +
                # For example, if you want to add a 10 pixel buffer to the bottom of a
         | 
| 255 | 
            +
                # line of text:
         | 
| 256 | 
            +
                #
         | 
| 257 | 
            +
                #    pad_bottom(10) { add_text "This will be padded on top" }
         | 
| 190 258 | 
             
                def pad_bottom(y,&block)
         | 
| 191 259 | 
             
                  block.call
         | 
| 192 260 | 
             
                  move_cursor(-y)
         | 
| 193 261 | 
             
                end
         | 
| 194 | 
            -
             | 
| 262 | 
            +
                
         | 
| 263 | 
            +
                # Draws a PDF::SimpleTable using the given data (usually a Data::Table)
         | 
| 264 | 
            +
                # Takes all the options you can set on a PDF::SimpleTable object,
         | 
| 265 | 
            +
                # see the PDF::Writer API docs for details, or check our quick reference
         | 
| 266 | 
            +
                # at: 
         | 
| 267 | 
            +
                # 
         | 
| 268 | 
            +
                # http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/PdfWriterQuickRef
         | 
| 195 269 | 
             
                def draw_table(table_data, format_opts={})
         | 
| 196 | 
            -
                  m = " | 
| 197 | 
            -
                  raise m if table_data.column_names.empty?
         | 
| 270 | 
            +
                  m = "PDF Formatter requires column_names to be defined"
         | 
| 271 | 
            +
                  raise FormatterError, m if table_data.column_names.empty?
         | 
| 272 | 
            +
                  
         | 
| 273 | 
            +
                  table_data.rename_columns { |c| c.to_s } 
         | 
| 198 274 |  | 
| 199 275 | 
             
                  format_opts = table_format.merge(format_opts) if table_format  
         | 
| 200 276 |  | 
| @@ -210,38 +286,53 @@ module Ruport | |
| 210 286 | 
             
                    table.render_on(pdf_writer)
         | 
| 211 287 | 
             
                  end
         | 
| 212 288 | 
             
                end
         | 
| 213 | 
            -
             | 
| 289 | 
            +
                
         | 
| 290 | 
            +
                # This module provides tools to simplify some common drawing operations
         | 
| 291 | 
            +
                # it is included by default in the PDF formatter
         | 
| 292 | 
            +
                #
         | 
| 214 293 | 
             
                module DrawingHelpers
         | 
| 215 | 
            -
             | 
| 294 | 
            +
                  
         | 
| 295 | 
            +
                  # draws a horizontal line from x1 to x2
         | 
| 216 296 | 
             
                  def horizontal_line(x1,x2)
         | 
| 217 297 | 
             
                    pdf_writer.line(x1,cursor,x2,cursor)
         | 
| 218 298 | 
             
                    pdf_writer.stroke
         | 
| 219 299 | 
             
                  end
         | 
| 220 | 
            -
             | 
| 300 | 
            +
                                
         | 
| 301 | 
            +
                  # draws a vertical line at x from y1 to y2
         | 
| 221 302 | 
             
                  def vertical_line_at(x,y1,y2)
         | 
| 222 303 | 
             
                    pdf_writer.line(x,y1,x,y2)
         | 
| 304 | 
            +
                    pdf_writer.stroke 
         | 
| 223 305 | 
             
                  end
         | 
| 224 | 
            -
             | 
| 306 | 
            +
                
         | 
| 307 | 
            +
                  # Alias for PDF::Writer#absolute_left_margin
         | 
| 225 308 | 
             
                  def left_boundary
         | 
| 226 309 | 
             
                    pdf_writer.absolute_left_margin
         | 
| 227 310 | 
             
                  end
         | 
| 228 | 
            -
             | 
| 311 | 
            +
                  
         | 
| 312 | 
            +
                  # Alias for PDF::Writer#absolute_right_margin
         | 
| 229 313 | 
             
                  def right_boundary
         | 
| 230 314 | 
             
                    pdf_writer.absolute_right_margin
         | 
| 231 315 | 
             
                  end
         | 
| 232 | 
            -
             | 
| 316 | 
            +
                  
         | 
| 317 | 
            +
                  # Alias for PDF::Writer#absolute_top_margin
         | 
| 233 318 | 
             
                  def top_boundary
         | 
| 234 319 | 
             
                    pdf_writer.absolute_top_margin
         | 
| 235 320 | 
             
                  end
         | 
| 236 | 
            -
             | 
| 321 | 
            +
                  
         | 
| 322 | 
            +
                  # Alias for PDF::Writer#absolute_bottom_margin
         | 
| 237 323 | 
             
                  def bottom_boundary
         | 
| 238 324 | 
             
                    pdf_writer.absolute_bottom_margin
         | 
| 239 325 | 
             
                  end
         | 
| 240 | 
            -
             | 
| 326 | 
            +
                  
         | 
| 327 | 
            +
                  # Alias for PDF::Writer#y
         | 
| 241 328 | 
             
                  def cursor
         | 
| 242 329 | 
             
                    pdf_writer.y
         | 
| 243 330 | 
             
                  end
         | 
| 244 | 
            -
             | 
| 331 | 
            +
                  
         | 
| 332 | 
            +
                  # Draws text at an absolute location, defined by
         | 
| 333 | 
            +
                  # :y, :x1|:left, :x2|:right 
         | 
| 334 | 
            +
                  # 
         | 
| 335 | 
            +
                  # All usual options to add_text are also supported
         | 
| 245 336 | 
             
                  def draw_text(text,text_opts)
         | 
| 246 337 | 
             
                    move_cursor_to(text_opts[:y]) if text_opts[:y]
         | 
| 247 338 | 
             
                    add_text(text,
         | 
| @@ -288,7 +379,7 @@ module Ruport | |
| 288 379 | 
             
                  data.each do |name,group|
         | 
| 289 380 | 
             
                    group_column = { data.grouped_by => "<b>#{name}</b>\n" }
         | 
| 290 381 | 
             
                    group.each_with_index do |rec,i|
         | 
| 291 | 
            -
                      i == 0 ? table << group_column.merge(rec. | 
| 382 | 
            +
                      i == 0 ? table << group_column.merge(rec.to_hash) : table << rec
         | 
| 292 383 | 
             
                    end
         | 
| 293 384 | 
             
                    table << Array.new(grouping_columns.length,' ') if style == :separated
         | 
| 294 385 | 
             
                  end
         |