
#==============================================================================#
# $Id: chart.rb,v 1.2 2004/01/23 00:38:04 yuya Exp $
# $Source: /cvsroot/gruby/gruby/lib/grb/chart/line/chart.rb,v $
#==============================================================================#

require 'grb/chart/xy_base/chart'

#==============================================================================#

class Array

  def peep(size)
    return (0..(self.size - size)).collect { |i|
      yield(self[i, size])
    }
  end

end # Array

#==============================================================================#

module GRb

  module Chart

    class LineChart < XYChartBase

      def initialize(property, major_scale, items)
        super(property)
        @value_set   = []
        @major_scale = major_scale
        @items       = items
      end

      def add_value(name, values, color, marker)
        @value_set << ValueSet.new(name, values, color, marker)
      end

      def draw(image, box)
        @value_set.each { |value_set|
          chart = LineChart.new
          chart.scale  = @major_scale
          chart.value  = (value_set.values + [nil] * @items)[0, @items]
          chart.color  = value_set.color
          chart.marker = value_set.marker
          chart.draw(image, box)
        }
      end

      class ValueSet

        def initialize(name, values, color, marker)
          @name   = name
          @values = values
          @color  = color
          @marker = marker
        end

        attr_reader :name, :values, :color, :marker

      end # ValueSet

      class LineChart

        def initialize
          @scale  = nil
          @value  = nil
          @color  = nil
          @marker = nil
        end

        attr_accessor :scale, :value, :color, :marker

        def draw(image, box)
          point = calculate(@value, @scale, box)

          point.peep(2) { |(x1, y1), (x2, y2)|
            if x1 && y1 && x2 && y2
              image.line(x1, y1, x2, y2, @color)
            end
          }

          if @marker
            point.each { |x, y|
              if x && y
                @marker.draw(image, x, y)
              end
            }
          end
        end

        def calculate(value, scale, box)
          width = (box.dx - 1).to_f / value.size
          raito = scale.raito(box.dy - 1)
          start = box.x + width / 2.0

          index = -1

          return value.collect { |val|
            index += 1

            if val
              x = start + width * index
              y = box.y2 - (val - scale.minimum) * raito
              [x, y]
            else
              [nil, nil]
            end
          }
        end

      end # LineChart

    end # LineChart

  end # Graph

end # GRb

#==============================================================================#
#==============================================================================#
