class SvgDrawer::Base

Attributes

default_params[R]
required_params[R]
special_params[R]
child_params[R]
height[W]
inherited_params[R]
params[R]
width[W]

Public Class Methods

defaults(hash) click to toggle source

The default_values is a hash of param values that will be used as a last-resort fallback

With and height are applicable to all elements, so they are always included here to avoid “No such param” errors (see ParamMerger#param for details)

# File lib/svg_drawer/base.rb, line 43
def defaults(hash)
  default_params.update(hash)
end
new(params = {}) click to toggle source

All elements can are initialized with a params hash only. This hash contains stuff regular keys like :width, :height, etc. If this hash does not contain any of the keys found in self.class.required_params, an error is risen. It may contain an :inherited. Its value is a hash which will serve as a fall-back to any keys not found in the top-level hash. For example: { width: 100, inherited: { width: 200, height: 500 } }

Calling param(:width) on the element will return 100 Calling param(:height) on the element will return 500 Calling param(:foo) will not be found in any of the hashes, so it will be looked up in self.class.default_params:

- if found, will be returned
- if not found, an error will be risen (see ParameterMerger#param)

A special @child_params hash is automatically constructed every time update_params! is called (incl. initialize) It is a hash that will be passed on as the value of the :inherited key to any child elements constructed. Note that it will not contain any keys found in self.class.special_params

Inheritance example:

Table.new(font: 'A') do |table|
  table.row do |row|
    row.cell do |cell|
      cell.content = TextBox.new('foo')      # text 1
    end

  table.row(font: 'B') do |row|
    row.cell do |cell|
      cell.content = TextBox.new('foo')      # text 2
    end

    row.cell(font: 'C') do |cell|
      cell.content = TextBox.new('foo')      # text 3
    end

    row.cell(font: 'C') do |cell|
      cell.content(TextBox.new('foo', font: 'D')) # text 4
    end
  end
end

The texts 1, 2, 3 and 4 will have font 'A', 'B', 'C' and 'D'.

# File lib/svg_drawer/base.rb, line 122
def initialize(params = {})
  @params = {}
  @inherited_params = {}
  @child_params = {}
  @pmerger = Utils::ParameterMerger.new(@params,
                                        @inherited_params,
                                        self.class.default_params)

  update_params!(params)
end
requires(*names) click to toggle source

The required_params contain param keys vital to the element. For example, a table can't be initialized without a :columns param. Their values can be provided via inherited_params.

# File lib/svg_drawer/base.rb, line 17
def requires(*names)
  required_params.concat(names)
end
special(*names) click to toggle source

The special_params contain param keys special to the element. They will not be stored in @child_params See note in initialize

# File lib/svg_drawer/base.rb, line 26
def special(*names)
  # Ensure special param are also a valid param (see ParameterMerger#param)
  names_hash = names.map { |n| [n, nil] }.to_h

  # this just Hash#reverse_merge! as implemented in activesupport-4.2
  default_params.merge!(names_hash) { |_key, left, _right| left }
  special_params.concat(names)
end

Public Instance Methods

draw(*args, debug: false) click to toggle source
# File lib/svg_drawer/base.rb, line 155
def draw(*args, debug: false)
  ensure_complete!
  @debug = debug
  _draw(*args)
end
ensure_complete!() click to toggle source
# File lib/svg_drawer/base.rb, line 161
def ensure_complete!
  pending_element = incomplete
  raise ElementIncomplete, pending_element if pending_element
end
height() click to toggle source
# File lib/svg_drawer/base.rb, line 174
def height
  raise NotImplementedError
end
incomplete() click to toggle source
# File lib/svg_drawer/base.rb, line 178
def incomplete
  raise NotImplementedError
end
param(name, default = nil) click to toggle source
# File lib/svg_drawer/base.rb, line 147
def param(name, default = nil)
  @pmerger.param(name) || default
end
param!(name) click to toggle source
# File lib/svg_drawer/base.rb, line 151
def param!(name)
  param(name) or raise "No default value for: #{name}"
end
update_params!(params) click to toggle source

The way to update an element's params

# File lib/svg_drawer/base.rb, line 134
def update_params!(params)
  @params.update(_deep_dup(params))
  @inherited_params.update(@params.delete(:inherited) || {})

  # Note: self.class.default_params is NOT to be merged in @child_params
  @child_params = @inherited_params.merge(@params)
  self.class.special_params.each { |name| @child_params.delete(name) }

  self.class.required_params.each do |rp|
    raise "Required param is missing: #{rp}" unless @pmerger.param?(rp)
  end
end
width() click to toggle source

To be defined in subclasses

# File lib/svg_drawer/base.rb, line 170
def width
  raise NotImplementedError
end

Private Instance Methods

_complete?() click to toggle source
# File lib/svg_drawer/base.rb, line 188
def _complete?
  raise NotImplementedError
end
_deep_dup(value) click to toggle source
# File lib/svg_drawer/base.rb, line 206
def _deep_dup(value)
  case value
  when Array then value.map { |v| _deep_dup(v) }
  when Hash then value.map { |k, v| [_deep_dup(k), _deep_dup(v)] }.to_h
  when Integer, Float, Symbol, TrueClass, FalseClass then value
  else value.dup
  end
end
_draw(*) click to toggle source
# File lib/svg_drawer/base.rb, line 184
def _draw(*)
  raise NotImplementedError
end
draw_border(svg, width_override: width, height_override: height) click to toggle source
# File lib/svg_drawer/base.rb, line 192
def draw_border(svg, width_override: width, height_override: height)
  borders = param(:borders)
  borders ||= %i[left right top bottom] if param(:border)
  Border.draw(
    svg,
    width_override,
    height_override,
    borders,
    param(:border_style),
    param(:class),
    @debug
  )
end