lib/prawn/graph/chart_components/series_renderer.rb
module Prawn
module Graph
module ChartComponents
# The Prawn::Graph::ChartComponents::SeriesRenderer is used to plot indivdual Prawn::Graph::Series on
# a Prawn::Graph::ChartComponents::Canvas and its associated Prawn::Document.
#
class SeriesRenderer
# @param series [Prawn::Graph::Series]
# @param canvas [Prawn::Graph::ChartComponents::Canvas]
#
def initialize(series, canvas, color = '000000')
if series.is_a?(Array)
raise ArgumentError.new("series must be a Prawn::Graph::Series") unless series.first.is_a?(Prawn::Graph::Series)
else
raise ArgumentError.new("series must be a Prawn::Graph::Series") unless series.is_a?(Prawn::Graph::Series)
end
raise ArgumentError.new("canvas must be a Prawn::Graph::ChartComponents::Canvas") unless canvas.is_a?(Prawn::Graph::ChartComponents::Canvas)
@series = series
@canvas = canvas
@prawn = canvas.prawn
@color = color
@graph_area = @canvas.layout.graph_area
@plot_area_width = @graph_area.width - 25
@plot_area_height = @graph_area.height - 20
end
def render
render_chart
end
private
def render_chart
raise "Subclass Me"
end
def render_axes
prawn.stroke_color = @canvas.theme.axes
prawn.fill_color = @canvas.theme.axes
prawn.stroke_horizontal_line(0, @plot_area_width, at: 0)
prawn.stroke_vertical_line(0, @plot_area_height, at: 0)
prawn.fill_and_stroke_ellipse [ 0,0], 1
add_y_axis_label(max)
add_y_axis_label(min)
add_y_axis_label(avg)
add_y_axis_label(mid)
add_x_axis_labels
end
def add_x_axis_labels
return if @canvas.options[:xaxis_labels].size.zero?
width_of_each_label = (@plot_area_width / @canvas.options[:xaxis_labels].size) - 1
@canvas.options[:xaxis_labels].each_with_index do |label, i|
offset = i + 1
position = ((offset * width_of_each_label) - width_of_each_label) + 1
prawn.text_box label, at: [ position, -2 ], width: width_of_each_label, height: 6, valign: :center, align: :center,
overflow: :shrink_to_fit
end
end
def add_y_axis_label(value)
unless value.zero?
y = (point_height_percentage(value) * @plot_area_height)
prawn.text_box "#{value}", at: [-14, y], height: 5, overflow: :shrink_to_fit, width: 12, valign: :bottom, align: :right
end
end
# Calculates the relative height of a given point based on the maximum value present in
# the series.
#
def point_height_percentage(value)
((BigDecimal(value, 10)/BigDecimal(@canvas.series.collect(&:max).max, 10)) * BigDecimal(1)).round(2) rescue 0
end
def prawn
@prawn
end
def max
@series.max || 0
end
def min
@series.min || 0
end
def avg
@series.avg || 0
end
def mid
(min + max) / 2 rescue 0
end
def draw_marker_point(color, x_position, y_position)
prawn.save_graphics_state do
prawn.fill_color = color
prawn.stroke_color = color
prawn.line_width = 1
prawn.dash(2)
prawn.stroke_line([x_position, 0], [x_position, y_position])
prawn.undash
prawn.fill_ellipse([x_position, y_position ], 2)
return true
end
end
end
end
end
end