lib/prawn/grid.rb in prawn-2.4.0 vs lib/prawn/grid.rb in prawn-2.5.0
- old
+ new
@@ -1,85 +1,136 @@
# frozen_string_literal: true
-# grid.rb: Provides a basic grid layout system for Prawn
-#
-# Contributed by Andrew O'Brien in March 2009
-#
-# This is free software. Please see the LICENSE and COPYING files for details.
-
module Prawn
- class Document
+ class Document # rubocop: disable Style/Documentation
# @group Experimental API
- # Defines the grid system for a particular document. Takes the number of
+ # Defines the grid system for a particular document. Takes the number of
# rows and columns and the width to use for the gutter as the
# keys :rows, :columns, :gutter, :row_gutter, :column_gutter
#
- # Note that a completely new grid object is built each time define_grid()
- # is called. This means that all subsequent calls to grid() will use
- # the newly defined Grid object -- grids are not nestable like
- # bounding boxes are.
-
+ # @note A completely new grid object is built each time `define_grid`
+ # is called. This means that all subsequent calls to grid() will use
+ # the newly defined Grid object -- grids are not nestable like
+ # bounding boxes are.
+ #
+ # @param options [Hash{Symbol => any}]
+ # @option options :columns [Integer] Number of columns in the grid.
+ # @option options :rows [Integer] Number of rows in the grid.
+ # @option options :gutter [Number] Gutter size. `:row_gutter` and
+ # `:column_gutter` are ignored if specified.
+ # @option options :row_gutter [Number] Row gutter size.
+ # @option options :column_gutter [Number] Column gutter size.
+ # @return [Grid]
def define_grid(options = {})
@boxes = nil
@grid = Grid.new(self, options)
end
# A method that can either be used to access a particular grid on the page
# or work with the grid system directly.
#
- # @pdf.grid # Get the Grid directly
- # @pdf.grid([0,1]) # Get the GridBox at [0,1]
- # @pdf.grid([0,1], [1,2]) # Get a multi-box spanning from [0,1] to [1,2]
+ # @overload grid
+ # Get current grid.
#
+ # @return [Grid]
+ #
+ # @overload grid(row, column)
+ # Get a grid box.
+ #
+ # @param row [Integer]
+ # @param column [Integer]
+ # @return [GridBox]
+ #
+ # @overload grid(box1, box2)
+ # Get a grid multi-box.
+ #
+ # @param box1 [Array(Integer, Integer)] Start box coordinates.
+ # @param box2 [Array(Integer, Integer)] End box coordinates.
+ # @return [MultiBox]
def grid(*args)
@boxes ||= {}
@boxes[args] ||=
- begin
- if args.empty?
- @grid
- else
- g1, g2 = args
+ if args.empty?
+ @grid
+ else
+ g1, g2 = args
- if g1.is_a?(Array) && g2.is_a?(Array) &&
- g1.length == 2 && g2.length == 2
- multi_box(single_box(*g1), single_box(*g2))
- else
- single_box(g1, g2)
- end
+ if g1.is_a?(Array) && g2.is_a?(Array) &&
+ g1.length == 2 && g2.length == 2
+ multi_box(single_box(*g1), single_box(*g2))
+ else
+ single_box(g1, g2)
end
end
end
# A Grid represents the entire grid system of a Page and calculates
# the column width and row height of the base box.
#
# @group Experimental API
class Grid
- attr_reader :pdf, :columns, :rows, :gutter, :row_gutter, :column_gutter
+ # @private
+ # @return [Prawn::Document]
+ attr_reader :pdf
- def initialize(pdf, options = {}) # :nodoc:
+ # Number of columns in the grid.
+ # @return [Integer]
+ attr_reader :columns
+
+ # Number of rows in the grid.
+ # @return [Integer]
+ attr_reader :rows
+
+ # Gutter size.
+ # @return [Number]
+ attr_reader :gutter
+
+ # Row gutter size.
+ # @return [Number]
+ attr_reader :row_gutter
+
+ # Column gutter size.
+ # @return [Number]
+ attr_reader :column_gutter
+
+ # @param pdf [Prawn::Document]
+ # @param options [Hash{Symbol => any}]
+ # @option options :columns [Integer] Number of columns in the grid.
+ # @option options :rows [Integer] Number of rows in the grid.
+ # @option options :gutter [Number] Gutter size. `:row_gutter` and
+ # `:column_gutter` are ignored if specified.
+ # @option options :row_gutter [Number] Row gutter size.
+ # @option options :column_gutter [Number] Column gutter size.
+ def initialize(pdf, options = {})
valid_options = %i[columns rows gutter row_gutter column_gutter]
- Prawn.verify_options valid_options, options
+ Prawn.verify_options(valid_options, options)
@pdf = pdf
@columns = options[:columns]
@rows = options[:rows]
apply_gutter(options)
end
# Calculates the base width of boxes.
+ #
+ # @return [Float]
def column_width
@column_width ||= subdivide(pdf.bounds.width, columns, column_gutter)
end
# Calculates the base height of boxes.
+ #
+ # @return [Float]
def row_height
@row_height ||= subdivide(pdf.bounds.height, rows, row_gutter)
end
- # Diagnostic tool to show all of the grids. Defaults to gray.
+ # Diagnostic tool to show all of the grid boxes.
+ #
+ # @param color [Color]
+ # @return [void]
def show_all(color = 'CCCCCC')
rows.times do |row|
columns.times do |column|
pdf.grid(row, column).show(color)
end
@@ -87,32 +138,33 @@
end
private
def subdivide(total, num, gutter)
- (total.to_f - (gutter * (num - 1).to_f)) / num.to_f
+ (Float(total) - (gutter * Float((num - 1)))) / Float(num)
end
def apply_gutter(options)
if options.key?(:gutter)
- @gutter = options[:gutter].to_f
+ @gutter = Float(options[:gutter])
@row_gutter = @gutter
@column_gutter = @gutter
else
- @row_gutter = options[:row_gutter].to_f
- @column_gutter = options[:column_gutter].to_f
+ @row_gutter = Float(options[:row_gutter])
+ @column_gutter = Float(options[:column_gutter])
@gutter = 0
end
end
end
# A Box is a class that represents a bounded area of a page.
# A Grid object has methods that allow easy access to the coordinates of
- # its corners, which can be plugged into most existing prawnmethods.
+ # its corners, which can be plugged into most existing Prawn methods.
#
# @group Experimental API
class GridBox
+ # @private
attr_reader :pdf
def initialize(pdf, rows, columns)
@pdf = pdf
@rows = rows
@@ -120,86 +172,115 @@
end
# Mostly diagnostic method that outputs the name of a box as
# col_num, row_num
#
+ # @return [String]
def name
"#{@rows},#{@columns}"
end
- # :nodoc
+ # @private
def total_height
- pdf.bounds.height.to_f
+ Float(pdf.bounds.height)
end
- # Width of a box
+ # Width of a box.
+ #
+ # @return [Float]
def width
- grid.column_width.to_f
+ Float(grid.column_width)
end
- # Height of a box
+ # Height of a box.
+ #
+ # @return [Float]
def height
- grid.row_height.to_f
+ Float(grid.row_height)
end
- # Width of the gutter
+ # Width of the gutter.
+ #
+ # @return [Float]
def gutter
- grid.gutter.to_f
+ Float(grid.gutter)
end
- # x-coordinate of left side
+ # x-coordinate of left side.
+ #
+ # @return [Float]
def left
- @left ||= (width + grid.column_gutter) * @columns.to_f
+ @left ||= (width + grid.column_gutter) * Float(@columns)
end
- # x-coordinate of right side
+ # x-coordinate of right side.
+ #
+ # @return [Float]
def right
@right ||= left + width
end
- # y-coordinate of the top
+ # y-coordinate of the top.
+ #
+ # @return [Float]
def top
- @top ||= total_height - ((height + grid.row_gutter) * @rows.to_f)
+ @top ||= total_height - ((height + grid.row_gutter) * Float(@rows))
end
- # y-coordinate of the bottom
+ # y-coordinate of the bottom.
+ #
+ # @return [Float]
def bottom
@bottom ||= top - height
end
- # x,y coordinates of top left corner
+ # x,y coordinates of top left corner.
+ #
+ # @return [Array(Float, Float)]
def top_left
[left, top]
end
- # x,y coordinates of top right corner
+ # x,y coordinates of top right corner.
+ #
+ # @return [Array(Float, Float)]
def top_right
[right, top]
end
- # x,y coordinates of bottom left corner
+ # x,y coordinates of bottom left corner.
+ #
+ # @return [Array(Float, Float)]
def bottom_left
[left, bottom]
end
- # x,y coordinates of bottom right corner
+ # x,y coordinates of bottom right corner.
+ #
+ # @return [Array(Float, Float)]
def bottom_right
[right, bottom]
end
# Creates a standard bounding box based on the grid box.
+ #
+ # @yield
+ # @return [void]
def bounding_box(&blk)
pdf.bounding_box(top_left, width: width, height: height, &blk)
end
- # Diagnostic method
+ # Drawn the box. Diagnostic method.
+ #
+ # @param grid_color [Color]
+ # @return [void]
def show(grid_color = 'CCCCCC')
bounding_box do
original_stroke_color = pdf.stroke_color
pdf.stroke_color = grid_color
- pdf.text name
+ pdf.text(name)
pdf.stroke_bounds
pdf.stroke_color = original_stroke_color
end
end
@@ -218,73 +299,119 @@
def initialize(pdf, box1, box2)
@pdf = pdf
@boxes = [box1, box2]
end
+ # @private
attr_reader :pdf
+ # Mostly diagnostic method that outputs the name of a box.
+ #
+ # @return [String]
def name
@boxes.map(&:name).join(':')
end
+ # @private
def total_height
@boxes[0].total_height
end
+ # Width of a box.
+ #
+ # @return [Float]
def width
right_box.right - left_box.left
end
+ # Height of a box.
+ #
+ # @return [Float]
def height
top_box.top - bottom_box.bottom
end
+ # Width of the gutter.
+ #
+ # @return [Float]
def gutter
@boxes[0].gutter
end
+ # x-coordinate of left side.
+ #
+ # @return [Float]
def left
left_box.left
end
+ # x-coordinate of right side.
+ #
+ # @return [Float]
def right
right_box.right
end
+ # y-coordinate of the top.
+ #
+ # @return [Float]
def top
top_box.top
end
+ # y-coordinate of the bottom.
+ #
+ # @return [Float]
def bottom
bottom_box.bottom
end
+ # x,y coordinates of top left corner.
+ #
+ # @return [Array(Float, Float)]
def top_left
[left, top]
end
+ # x,y coordinates of top right corner.
+ #
+ # @return [Array(Float, Float)]
def top_right
[right, top]
end
+ # x,y coordinates of bottom left corner.
+ #
+ # @return [Array(Float, Float)]
def bottom_left
[left, bottom]
end
+ # x,y coordinates of bottom right corner.
+ #
+ # @return [Array(Float, Float)]
def bottom_right
[right, bottom]
end
+ # Creates a standard bounding box based on the grid box.
+ #
+ # @yield
+ # @return [void]
def bounding_box(&blk)
pdf.bounding_box(top_left, width: width, height: height, &blk)
end
+ # Drawn the box. Diagnostic method.
+ #
+ # @param grid_color [Color]
+ # @return [void]
def show(grid_color = 'CCCCCC')
bounding_box do
original_stroke_color = pdf.stroke_color
pdf.stroke_color = grid_color
- pdf.text name
+ pdf.text(name)
pdf.stroke_bounds
pdf.stroke_color = original_stroke_color
end
end