From 8b12344c7b6bd579fcdded7f42f8452f743a2a77 Mon Sep 17 00:00:00 2001 From: Andy Meneely Date: Tue, 29 Jul 2014 00:16:47 -0400 Subject: [PATCH] Tons of docs, xlsx can be used outside Deck now --- lib/squib/api/background.rb | 9 +++-- lib/squib/api/data.rb | 67 ++++++++++++++++++++++------------ lib/squib/api/image.rb | 38 ++++++++++--------- lib/squib/api/save.rb | 7 +++- lib/squib/api/settings.rb | 12 +++--- lib/squib/api/shapes.rb | 25 +++++++------ lib/squib/api/text.rb | 37 ++++++++++--------- lib/squib/deck.rb | 19 +++++++++- lib/squib/graphics/save_doc.rb | 15 +++++++- lib/squib/input_helpers.rb | 14 ++++--- 10 files changed, 155 insertions(+), 88 deletions(-) diff --git a/lib/squib/api/background.rb b/lib/squib/api/background.rb index 11b3191..d85492f 100644 --- a/lib/squib/api/background.rb +++ b/lib/squib/api/background.rb @@ -1,11 +1,12 @@ module Squib class Deck # Fills the background with the given color + # @example + # background color: :white # - # @params opts: the parameter hash. - # @option range: the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} - # @option color: the color the font will render to. See {file:API.md#label-Specifying+Colors Specifying Colors} - # @return [nil] + # @option range [Enumerable] (:all) the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} + # @option color [String] (:black) the color the font will render to. See {file:API.md#label-Specifying+Colors Specifying Colors} + # @return [nil] nothing # @api public def background(opts = {}) opts = needs(opts,[:range, :color]) diff --git a/lib/squib/api/data.rb b/lib/squib/api/data.rb index 316d83a..5221554 100644 --- a/lib/squib/api/data.rb +++ b/lib/squib/api/data.rb @@ -1,32 +1,51 @@ require 'roo' module Squib - class Deck - # Convenience method for pulling Excel data from `.xlsx` files - # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. - # See the example at {file:samples/excel.rb samples/excel.rb}. The accompanying Excel file is in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) - # - # @param file: [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory. - # @param sheet: [Integer] The zero-based index of the sheet from which to read. - # @api public + # Pulls Excel data from `.xlsx` files into a column-based hash + # + # Pulls the data into a Hash of arrays based on the columns. First row is assumed to be the header row. + # See the example `samples/excel.rb` in the [source repository](https://github.com/andymeneely/squib/tree/master/samples) + # + # @example + # # Excel file looks like this: + # # | h1 | h2 | + # # ------------ + # # | 1 | 2 | + # # | 3 | 4 | + # data = xlsx file: 'data.xlsx', sheet: 0 + # {'h1' => [1,3], 'h2' => [2,4]} + # + # @option opts file [String] the file to open. Must end in `.xlsx`. Opens relative to the current directory. + # @option opts sheet [Integer] (0) The zero-based index of the sheet from which to read. + # @return [Hash] a hash of arrays based on columns in the spreadsheet + # @api public + def xlsx(opts = {}) + opts = Squib::SYSTEM_DEFAULTS.merge(opts) + opts = Squib::InputHelpers.fileify(opts) + s = Roo::Excelx.new(opts[:file]) + s.default_sheet = s.sheets[opts[:sheet]] + data = {} + s.first_column.upto(s.last_column) do |col| + header = s.cell(s.first_row,col).to_s + data[header] = [] + (s.first_row+1).upto(s.last_row) do |row| + cell = s.cell(row,col) + # Roo hack for avoiding unnecessary .0's on whole integers + cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, "General"] + data[header] << cell + end#row + end#col + data + end#xlsx + module_function :xlsx + + class Deck + + # Convenience call for Squib.xlsx def xlsx(opts = {}) - opts = needs(opts, [:file, :sheet]) - s = Roo::Excelx.new(opts[:file]) - s.default_sheet = s.sheets[opts[:sheet]] - data = {} - s.first_column.upto(s.last_column) do |col| - header = s.cell(s.first_row,col).to_s - data[header] = [] - (s.first_row+1).upto(s.last_row) do |row| - cell = s.cell(row,col) - # Roo hack for avoiding unnecessary .0's on whole integers - cell = s.excelx_value(row,col) if s.excelx_type(row,col) == [:numeric_or_formula, "General"] - data[header] << cell - end#row - end#col - data - end#xlsx + Squib.xlsx(opts) + end end end diff --git a/lib/squib/api/image.rb b/lib/squib/api/image.rb index 27793b0..1b59d18 100644 --- a/lib/squib/api/image.rb +++ b/lib/squib/api/image.rb @@ -2,15 +2,18 @@ module Squib class Deck # Renders a png file at the given location. - # See {file:samples/image.rb samples/image.rb} and {file:samples/tgc-overlay.rb samples/tgc-overlay.rb} as examples. - # Note: scaling not currently supported for PNGs. # - # @param range: the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} - # @param file: file(s) to read in. If it's a single file, then it's use for every card. If the parameter is an Array of files, then each file is looked up for each card. See {file:API.md#Specifying+Files Specifying Files} - # @param x: the x-coordinate to place - # @param y: the y-coordinate to place - # @param alpha: the alpha-transparency percentage used to blend this image - # @return [nil] intended to be void + # See {file:samples/image.rb samples/image.rb} and {file:samples/tgc-overlay.rb samples/tgc-overlay.rb} as examples. + # Note: scaling not currently supported for PNGs. + # @example + # png file: 'img.png', x: 50, y: 50 + # + # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} + # @option opts file [String, Array] ('') file(s) to read in. If it's a single file, then it's use for every card in range. If the parameter is an Array of files, then each file is looked up for each card. See {file:API.md#Specifying+Files Specifying Files} + # @option opts x [Integer] (0) the x-coordinate to place + # @option opts y [Integer] (0) the y-coordinate to place + # @option opts alpha [Decimal] (1.0) the alpha-transparency percentage used to blend this image + # @return [nil] Returns nil # @api public def png(opts = {}) opts = needs(opts, [:range, :files, :x, :y, :alpha]) @@ -20,19 +23,18 @@ module Squib end # Renders an entire svg file at the given location. Uses the SVG-specified units and DPI to determine the pixel width and height. - # @example - # svg 1..2, 'icon.svg', '#stone', x: 50, y:50 # # See {file:samples/load-images.rb samples/load-images.rb} and {file:samples/tgc-overlay.rb samples/tgc-overlay.rb} as examples. + # @example + # svg 1..2, 'icon.svg', '#stone', x: 50, y:50 # - # @param range: the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} - # @param file: the svg file to render. See {file:API.md#Specifying+Files Specifying Files} - # @param id: if specified, only render the SVG element with the supplied id. Otherwise, render the entire SVG file - # @param x: the x-coordinate to place - # @param y: the y-coordinate to place - # @param width: the pixel width that the image should scale to. SVG scaling is done with vectors, so the scaling should be smooth. When set to `:native`, uses the DPI and units of the loaded SVG document. - # @param height: the pixel width that the image should scale to. SVG scaling is done with vectors, so the scaling should be smooth. When set to `:native`, uses the DPI and units of the loaded SVG document. - # @return [nil] essentially a void method + # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} + # @option opts file [String, Array] ('') file(s) to read in. If it's a single file, then it's use for every card in range. If the parameter is an Array of files, then each file is looked up for each card. See {file:API.md#Specifying+Files Specifying Files} + # @option opts x [Integer] (0) the x-coordinate to place + # @option opts y [Integer] (0) the y-coordinate to place + # @option opts width [Integer] (:native) the pixel width that the image should scale to. SVG scaling is done with vectors, so the scaling should be smooth. When set to `:native`, uses the DPI and units of the loaded SVG document. + # @option opts height [Integer] (:native) the pixel width that the image should scale to. SVG scaling is done with vectors, so the scaling should be smooth. When set to `:native`, uses the DPI and units of the loaded SVG document. + # @return [nil] Returns nil # @api public def svg(opts = {}) p = needs(opts,[:range, :files, :svgid, :x, :y, :width, :height]) diff --git a/lib/squib/api/save.rb b/lib/squib/api/save.rb index c46c5c6..ea2a061 100644 --- a/lib/squib/api/save.rb +++ b/lib/squib/api/save.rb @@ -16,11 +16,16 @@ module Squib self end - # Saves the given range of cards to PNG + # Saves the given range of cards to a PNG + # + # @example + # save range: 1..8, dir: '_pnp', prefix: 'bw_' # # @option opts [Enumerable] range (:all) the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} # @option opts [String] dir (_output) the directory for the output to be sent to. Will be created if it doesn't exist. # @option opts [String] prefix (card_) the prefix of the file name to be printed. + # @return [nil] Returns nothing + # @api public def save_png(opts = {}) opts = needs(opts,[:range, :creatable_dir, :prefix]) opts[:range].each do |i| diff --git a/lib/squib/api/settings.rb b/lib/squib/api/settings.rb index b2475a0..f4643e6 100644 --- a/lib/squib/api/settings.rb +++ b/lib/squib/api/settings.rb @@ -2,10 +2,13 @@ module Squib class Deck # Toggle hints globally. - # Text hints are rectangles around where the text will be laid out. They are intended to be temporary. - # Setting a hint to nil or to :off will disable hints. @see samples/text.rb # - # @param [Color] text the color of the text hint. To turn off use nil or :off. @see API.md + # Text hints are rectangles around where the text will be laid out. They are intended to be temporary. + # Setting a hint to nil or to :off will disable hints. @see samples/text.rb + # @example + # hint text:cyan + # + # @param [String] text the color of the text hint. To turn off use nil or :off. @see API.md # @return [nil] Returns nothing # @api public def hint(text: nil) @@ -20,8 +23,7 @@ module Squib # text 'blah24', font: 'Arial 24' # in Arial 24 # set font: :default # Back to Squib-wide default # - # @param opts: the hash of options. - # @option font: the font string to set as default. Can also be set to `:default` to use the Squib-wide default. + # @option opts font: the font string to set as default. Can also be set to `:default` to use the Squib-wide default. # @return [nil] Returns nothing # @api public def set(opts = {}) diff --git a/lib/squib/api/shapes.rb b/lib/squib/api/shapes.rb index ef1987a..4045333 100644 --- a/lib/squib/api/shapes.rb +++ b/lib/squib/api/shapes.rb @@ -2,18 +2,21 @@ module Squib class Deck # Draw a rounded rectangle + # + # @example + # rect x: 0, y: 0, width: 825, height: 1125, radius: 25 # - # @param opts: the hash of options. - # @option x: the x-coordinate to place - # @option y: the y-coordinate to place - # @option width: the width of the rectangle. - # @option height: the height of the rectangle. - # @option x_radius: the radius of the rounded corner horiztonally. Zero is a non-rounded corner. - # @option y_radius: the radius of the rounded corner vertically. Zero is a non-rounded corner. - # @option radius: when set, overrides both x_radius and y_radius - # @option fill_color: the color with which to fill the rectangle - # @option stroke_color: the color with which to stroke the outside of the rectangle - # @option stroke_width: the width of the outside stroke + # @option opts x [Integer] (0) the x-coordinate to place + # @option opts y [Integer] (0) the y-coordinate to place + # @option opts width [Integer] the width of the rectangle. + # @option opts height [Integer] the height of the rectangle. + # @option opts x_radius [Integer] (0) the radius of the rounded corner horiztonally. Zero is a non-rounded corner. + # @option opts y_radius [Integer] (0) the radius of the rounded corner vertically. Zero is a non-rounded corner. + # @option opts radius [Integer] (nil) when set, overrides both x_radius and y_radius + # @option opts fill_color [String] ('#0000') the color with which to fill the rectangle + # @option opts stroke_color [String] (:black) the color with which to stroke the outside of the rectangle + # @option opts stroke_width [Decimal] (2.0) the width of the outside stroke + # @return [nil] intended to be void # @api public def rect(opts = {}) opts = needs(opts, [:range, :x, :y, :width, :height, :radius, diff --git a/lib/squib/api/text.rb b/lib/squib/api/text.rb index 33c380d..816b1bf 100644 --- a/lib/squib/api/text.rb +++ b/lib/squib/api/text.rb @@ -2,31 +2,34 @@ module Squib class Deck # Renders a string at a given location, width, alignment, font, etc. + # # Unix-like newlines are interpreted even on Windows. + # See the {file:samples/text-options.rb samples/text.rb} for a lengthy example. # - # @example See the {file:samples/text-options.rb samples/text.rb} for a lengthy example. + # @example + # text str: 'hello' + # text str: 'hello', x: 50, y:50, align: center # - # @param range: the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} - # @param str: the string to be rendered. Must support `#to_s`. If the card responds to `#each`, it's mapped out one at a time across the cards. - # @param font: the Font description string, including family, styles, and size. + # @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:API.md#label-Specifying+Ranges Specifying Ranges} + # @option opts str [String, Array] ('') the string to be rendered. Must support `#to_s`. If the card responds to `#each`, it's mapped out one at a time across the cards. + # @option opts font [String] (Arial 36 or whatever was set with `set`) the Font description string, including family, styles, and size. # (e.g. `'Arial bold italic 12'`) # For the official documentation, see the [Pango docs](http://ruby-gnome2.sourceforge.jp/hiki.cgi?Pango%3A%3AFontDescription#style). # This [description](http://www.pygtk.org/pygtk2reference/class-pangofontdescription.html) is also quite good. # See the {file:samples/text-options.rb samples/text.rb} as well. - # @param x: the x-coordinate to place - # @param y: the y-coordinate to place - # @param options: captures the additional input options below - # @option color: (default: :black) the color the font will render to. See {file:API.md#label-Specifying+Colors Specifying Colors} - # @option markup: [Boolean] (default: false) Enable markup parsing of `str` using the HTML-like Pango Markup syntax, defined [here](http://ruby-gnome2.sourceforge.jp/hiki.cgi?pango-markup) and [here](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html). - # @option width: the width of the box the string will be placed in. Stretches to the content by default. - # @option height: the height of the box the string will be placed in. Stretches to the content by default. - # @option wrap: When height is set, determines the behavior of how the string wraps. The `:word_char` option will break at words, but then fall back to characters when the word cannot fit. # + # @option opts x [Integer] (0) the x-coordinate to place + # @option opts y [Integer] (0) the y-coordinate to place + # @option opts color [String] (:black) the color the font will render to. See {file:API.md#label-Specifying+Colors Specifying Colors} + # @option opts markup: [Boolean] (false) Enable markup parsing of `str` using the HTML-like Pango Markup syntax, defined [here](http://ruby-gnome2.sourceforge.jp/hiki.cgi?pango-markup) and [here](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html). + # @option opts width [Integer, :native] (:native) the width of the box the string will be placed in. Stretches to the content by default. + # @option opts height [Integer, :native] the height of the box the string will be placed in. Stretches to the content by default. + # @option opts wrap [:none, :word, :char, :word_char, true, false] (:word_char) When height is set, determines the behavior of how the string wraps. The `:word_char` option will break at words, but then fall back to characters when the word cannot fit. # # Options are `:none, :word, :char, :word_char`. Also: `true` is the same as `:word_char`, `false` is the same as `:none`. Default `:word_char` - # @option align: options `:left, :right, and :center`. Default `:left` - # @option justify: [Boolean] toggles whether or not the text is justified or not. Default `false` - # @option valign: When width and height are set, align text vertically according to the logical extents of the text. Options are `:top, :middle, :bottom`. Default `:top` - # @option ellipsize: When width and height are set, determines the behavior of overflowing text. Options are `:none, :start, :middle, :end`. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end` - # @option hint: show a text hint with the given color. Overrides global hints (see {Deck#hint}). + # @option opts align [:left, right, :center] (:left) The alignment of the text + # @option opts justify [Boolean] (false) toggles whether or not the text is justified or not. + # @option opts valign [:top, :middle, :bottom] (:top) When width and height are set, align text vertically according to the logical extents of the text. + # @option opts ellipsize [:none, :start, :middle, :end, true, false] (:end) When width and height are set, determines the behavior of overflowing text. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end` + # @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}). # @return [nil] Returns nothing # @api public def text(opts = {}) diff --git a/lib/squib/deck.rb b/lib/squib/deck.rb index 1241c09..c4ef54a 100644 --- a/lib/squib/deck.rb +++ b/lib/squib/deck.rb @@ -19,7 +19,22 @@ module Squib attr_reader :text_hint # Squib's constructor that sets the immutable properties. + # + # This is the starting point for Squib. In providing a block to the constructor, you have access to all of Deck's instance methods. + # The documented methods in Deck are the ones intended for use by most users. + # If your game requires multiple different sizes or orientations, I recommend using multiple `Squib::Deck`s in your `deck.rb`. You can modify the internals of `Squib::Deck` (e.g. `@cards`), but that's not recommended. + # @example + # require 'squib' + # Squib::Deck.new do + # text str: 'Hello, World!' + # end # + # @param width [Integer] the width of each card in pixels + # @param height [Integer] the height of each card in pixels + # @param cards [Integer] the number of cards in the deck + # @param dpi [Integer] the pixels per inch when rendering out to PDF or calculating using inches. + # @param config [String] the file used for global settings of this deck + # @param block [Block] the main body of the script. # @api public def initialize(width: 825, height: 1125, cards: 1, dpi: 300, config: 'config.yml', &block) @width=width; @height=height @@ -35,14 +50,14 @@ module Squib # Directly accesses the array of cards in the deck # - # @api public + # @api private def [](key) @cards[key] end # Iterates over each card in the deck # - # @api public + # @api private def each(&block) @cards.each { |card| block.call(card) } end diff --git a/lib/squib/graphics/save_doc.rb b/lib/squib/graphics/save_doc.rb index 106ab3e..36443e1 100644 --- a/lib/squib/graphics/save_doc.rb +++ b/lib/squib/graphics/save_doc.rb @@ -1,8 +1,20 @@ module Squib class Deck + # Lays out the cards in range and renders a PDF + # + # @example + # save_pdf file: 'deck.pdf', margin: 75, gap: 5, trim: 37 + # + # @option opts file [String] the name of the PDF file to save. + # @option opts dir [String] (_output) the directory to save to. Created if it doesn't exist. + # @option opts margin [Integer] (75) the margin around the outside of the page + # @option opts gap [Integer] (0) the space in pixels between the cards + # @option opts trim [Integer] (0) the space around the edge of each card to trim (e.g. to cut off the bleed margin for print-and-play) + # @return [nil] + # @api public def save_pdf(opts = {}) - p = needs(opts, [:file_to_save, :prefix, :margin, :gap, :trim]) + p = needs(opts, [:file_to_save, :creatable_dir, :margin, :gap, :trim]) width = 11 * @dpi ; height = 8.5 * @dpi #TODO: allow this to be specified too cc = Cairo::Context.new(Cairo::PDFSurface.new("#{p[:dir]}/#{p[:file]}", width, height)) x = p[:margin] ; y = p[:margin] @@ -22,6 +34,7 @@ module Squib end end + # @api private def trim(surface, trim, width, height) if trim > 0 tmp = Cairo::ImageSurface.new(width-2*trim, height-2*trim) diff --git a/lib/squib/input_helpers.rb b/lib/squib/input_helpers.rb index bda0192..8350b4c 100644 --- a/lib/squib/input_helpers.rb +++ b/lib/squib/input_helpers.rb @@ -3,6 +3,7 @@ require 'squib/constants' module Squib module InputHelpers + # @api private def needs(opts, params) opts = Squib::SYSTEM_DEFAULTS.merge(opts) opts = rangeify(opts) if params.include? :range @@ -21,12 +22,14 @@ module Squib end module_function :needs + # @api private def formatify(opts) opts[:format] = [opts[:format]].flatten opts end module_function :formatify + # @api private def rangeify (opts) range = opts[:range] raise 'Range cannot be nil' if range.nil? @@ -40,6 +43,7 @@ module Squib end module_function :rangeify + # @api private def fileify(opts, expand_singletons=false, allow_non_exist=false) opts[:file] = [opts[:file]] * @cards.size if expand_singletons files = [opts[:file]].flatten @@ -52,6 +56,7 @@ module Squib end module_function :fileify + # @api private def dirify(opts, allow_create=false) return opts if Dir.exists?(opts[:dir]) if allow_create @@ -64,7 +69,7 @@ module Squib end module_function :dirify - + # @api private def colorify(opts, nillable=false) if nillable # for optional color arguments like text hints opts[:color] = Cairo::Color.parse(opts[:color]) unless opts[:color].nil? @@ -75,6 +80,7 @@ module Squib end module_function :colorify + # @api private def fontify (opts) opts[:font] = @font if opts[:font]==:use_set opts[:font] = Squib::SYSTEM_DEFAULTS[:default_font] if opts[:font] == :default @@ -82,6 +88,7 @@ module Squib end module_function :fontify + # @api private def radiusify(opts) unless opts[:radius].nil? opts[:x_radius] = opts[:radius] @@ -91,6 +98,7 @@ module Squib end module_function :radiusify + # @api private def svgidify(opts) unless opts[:id].nil? opts[:id] = '#' << opts[:id] unless opts[:id].start_with? '#' @@ -99,9 +107,5 @@ module Squib end module_function :svgidify - def xyify - #TODO: Allow negative numbers that subtract from the card width & height. - end - end end \ No newline at end of file