
#==============================================================================#
# $Id: facade.rb,v 1.4 2004/01/23 05:24:11 yuya Exp $
# $Source: /cvsroot/gruby/gruby/lib/grb/chart/base/facade.rb,v $
#==============================================================================#

require 'grb/image'
require 'grb/chart/base/utility/box'
require 'grb/chart/base/parts/title'
require 'grb/chart/base/property/composite/frame'
require 'grb/chart/base/property/composite/title'
require 'grb/chart/base/property/composite/legend'
require 'grb/chart/base/decorator/align'
require 'grb/chart/base/decorator/split'

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

module GRb

  module Chart

    class ChartFacadeBase

      def initialize(image, x, y, dx, dy)
        @image = image
        @box   = Box.new(x, y, dx, dy)
        @data  = nil

        @property_frame  = self.create_property_frame
        @property_title  = self.create_property_title
        @property_legend = self.create_property_legend
        @property_chart  = self.create_property_chart
      end

      attr_accessor :image, :box, :data

      def self.create(dx, dy, truecolor = false)
        return self.new(GRb::Image.create(dx, dy, truecolor), 0, 0, dx, dy)
      end

      protected

      def create_property_frame
        return FrameProperty.new
      end

      def create_property_title
        return TitleProperty.new
      end

      def create_property_legend
        return LegendProperty.new
      end

      def create_property_chart
        raise(NotImplementedError, "don't use this class")
      end

      def build
        return @property_frame.create_decorator(self.layout)
      end

      def layout
        case [@property_title.visible, @property_legend.visible]
        when [true, true];   decorator = self.layout_title(self.build_title, self.layout_legend(self.build_legend, self.build_chart))
        when [true, false];  decorator = self.layout_title(self.build_title, self.build_chart)
        when [false, true];  decorator = self.layout_legend(self.build_legend, self.build_chart)
        when [false, false]; decorator = self.build_chart
        else raise 'bug?'
        end

        return decorator
      end

      def layout_title(title, graph)
        case @property_title.position
        when :top_center
          decorator = HorizontalAlignCenterDecorator.new(title)
          decorator = VerticalSplitUpperDecorator.new(decorator, graph)
        when :middle_left
          decorator = VerticalAlignCenterDecorator.new(title)
          decorator = HorizontalSplitLeftDecorator.new(decorator, graph)
        when :middle_right
          decorator = VerticalAlignCenterDecorator.new(title)
          decorator = HorizontalSplitRightDecorator.new(graph, decorator)
        when :bottom_center
          decorator = HorizontalAlignCenterDecorator.new(title)
          decorator = VerticalSplitLowerDecorator.new(graph, decorator)
        else
          raise ArgumentError, 'invalid position'
        end

        return decorator
      end

      def layout_legend(legend, graph)
        if @property_legend.vertical
          case @property_legend.position
          when :top_left
            decorator = VerticalAlignTopDecorator.new(legend)
            decorator = HorizontalSplitLeftDecorator.new(decorator, graph)
          when :top_right
            decorator = VerticalAlignTopDecorator.new(legend)
            decorator = HorizontalSplitRightDecorator.new(graph, decorator)
          when :middle_left
            decorator = VerticalAlignCenterDecorator.new(legend)
            decorator = HorizontalSplitLeftDecorator.new(decorator, graph)
          when :middle_right
            decorator = VerticalAlignCenterDecorator.new(legend)
            decorator = HorizontalSplitRightDecorator.new(graph, decorator)
          when :bottom_left
            decorator = VerticalAlignBottomDecorator.new(legend)
            decorator = HorizontalSplitLeftDecorator.new(decorator, graph)
          when :bottom_right
            decorator = VerticalAlignBottomDecorator.new(legend)
            decorator = HorizontalSplitRightDecorator.new(graph, decorator)
          else
            raise ArgumentError, 'invalid position'
          end
        else
          case @property_legend.position
          when :top_left
            decorator = HorizontalAlignLeftDecorator.new(legend)
            decorator = VerticalSplitUpperDecorator.new(decorator, graph)
          when :top_center
            decorator = HorizontalAlignCenterDecorator.new(legend)
            decorator = VerticalSplitUpperDecorator.new(decorator, graph)
          when :top_right
            decorator = HorizontalAlignRightDecorator.new(legend)
            decorator = VerticalSplitUpperDecorator.new(decorator, graph)
          when :bottom_left
            decorator = HorizontalAlignLeftDecorator.new(legend)
            decorator = VerticalSplitLowerDecorator.new(graph, decorator)
          when :bottom_center
            decorator = HorizontalAlignCenterDecorator.new(legend)
            decorator = VerticalSplitLowerDecorator.new(graph, decorator)
          when :bottom_right
            decorator = HorizontalAlignRightDecorator.new(legend)
            decorator = VerticalSplitLowerDecorator.new(graph, decorator)
          else
            raise ArgumentError, 'invalid position'
          end
        end

        return decorator
      end

      def build_title
        return @property_title.create_decorator(self.create_title(@property_title))
      end

      def build_legend
        return @property_legend.create_decorator(self.create_legend(@property_legend))
      end

      def build_chart
        return @property_chart.create_decorator(self.create_chart(@property_chart))
      end

      def create_title(property)
        return GRb::Chart::Title.new(property.font.create_font, property.text)
      end

      def create_legend(property)
        raise(NotImplementedError, "don't use this class")
      end

      def create_chart(property)
        raise(NotImplementedError, "don't use this class")
      end

      public

      def frame
        return @property_frame
      end

      def title
        return @property_title
      end

      def legend
        return @property_legend
      end

      def chart
        return @property_chart
      end

      def draw
        frame = self.build
        frame.draw(@image, @box)
      end

      def write_png(io)
        self.draw
        @image.write_png(io)
      end

      def write_png_file(filepath)
        File.open(filepath, 'wb') { |file|
          self.write_png(file)
        }
      end

      def write_png_cgi
        STDOUT.print "Content-Type: image/png\n\n"
        self.write_png(STDOUT)
      end

      def write_jpeg(io, quality)
        self.draw
        @image.write_jpeg(io, quality)
      end

      def write_jpeg_file(filepath, quality)
        File.open(filepath, 'wb') { |file|
          self.write_jpeg(file, quality)
        }
      end

      def write_jpeg_cgi
        STDOUT.print "Content-Type: image/jpeg\n\n"
        self.write_jpeg(STDOUT)
      end

      def interlace
        return @image.interlace
      end

      def interlace=(value)
        @image.interlace = value
      end

    end # ChartFacadeBase

  end # Graph

end # GRb

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