OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / lib / tkextlib / blt / component.rb
diff --git a/lib/ruby-1.9.1-rc1/ext/tk/lib/tkextlib/blt/component.rb b/lib/ruby-1.9.1-rc1/ext/tk/lib/tkextlib/blt/component.rb
new file mode 100644 (file)
index 0000000..b2005b2
--- /dev/null
@@ -0,0 +1,2145 @@
+#
+#  tkextlib/blt/component.rb
+#                               by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+
+require 'tk'
+require 'tkextlib/blt.rb'
+
+module Tk::BLT
+  module PlotComponent
+    include TkItemConfigMethod
+
+    module OptKeys
+      def __item_font_optkeys(id)
+        ['font', 'tickfont', 'titlefont']
+      end
+      private :__item_font_optkeys
+
+      def __item_numstrval_optkeys(id)
+        ['xoffset', 'yoffset']
+      end
+      private :__item_numstrval_optkeys
+
+      def __item_boolval_optkeys(id)
+        ['hide', 'under', 'descending', 'logscale', 'loose', 'showticks', 
+          'titlealternate', 'scalesymbols', 'minor', 'raised', 
+          'center', 'decoration', 'landscape', 'maxpect']
+      end
+      private :__item_boolval_optkeys
+
+      def __item_strval_optkeys(id)
+        ['text', 'label', 'limits', 'title', 
+          'show', 'file', 'maskdata', 'maskfile', 
+          'color', 'titlecolor', 'fill', 'outline', 'offdash']
+      end
+      private :__item_strval_optkeys
+
+      def __item_listval_optkeys(id)
+        ['bindtags']
+      end
+      private :__item_listval_optkeys
+
+      def __item_numlistval_optkeys(id)
+        ['dashes', 'majorticks', 'minorticks']
+      end
+      private :__item_numlistval_optkeys
+
+      def __item_tkvariable_optkeys(id)
+        ['variable', 'textvariable', 'colormap', 'fontmap']
+      end
+      private :__item_tkvariable_optkeys
+    end
+
+    include OptKeys
+
+    def __item_cget_cmd(id)
+      if id.kind_of?(Array)
+        # id := [ type, name ]
+        [self.path, id[0], 'cget', id[1]]
+      else
+        [self.path, id, 'cget']
+      end
+    end
+    private :__item_cget_cmd
+
+    def __item_config_cmd(id)
+      if id.kind_of?(Array)
+        # id := [ type, name, ... ]
+        type, *names = id
+        [self.path, type, 'configure'].concat(names)
+      else
+        [self.path, id, 'configure']
+      end
+    end
+    private :__item_config_cmd
+
+    def __item_pathname(id)
+      if id.kind_of?(Array)
+        id = tagid(id[1])
+      end
+      [self.path, id].join(';')
+    end
+    private :__item_pathname
+
+    def axis_cget(id, option)
+      ret = itemcget(['axis', tagid(id)], option)
+    end
+    def axis_cget_strict(id, option)
+      ret = itemcget_strict(['axis', tagid(id)], option)
+    end
+    def axis_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+        slot = _symbolkey2str(slot)
+        if cmd = slot.delete('command')
+          slot['command'] = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      else
+        value = slot
+        slot = args.pop
+        if slot == :command || slot == 'command'
+          cmd = value
+          value = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('axis')
+      itemconfigure(id_list, slot, value)
+    end
+    def axis_configinfo(id, slot=nil)
+      itemconfiginfo(['axis', tagid(id)], slot)
+    end
+    def current_axis_configinfo(id, slot=nil)
+      current_itemconfiginfo(['axis', tagid(id)], slot)
+    end
+
+    def crosshairs_cget(option)
+      itemcget('crosshairs', option)
+    end
+    def crosshairs_cget_strict(option)
+      itemcget_strict('crosshairs', option)
+    end
+    def crosshairs_configure(slot, value=None)
+      itemconfigure('crosshairs', slot, value)
+    end
+    def crosshairs_configinfo(slot=nil)
+      itemconfiginfo('crosshairs', slot)
+    end
+    def current_crosshairs_configinfo(slot=nil)
+      current_itemconfiginfo('crosshairs', slot)
+    end
+
+    def element_cget(id, option)
+      itemcget(['element', tagid(id)], option)
+    end
+    def element_cget_strict(id, option)
+      itemcget_strict(['element', tagid(id)], option)
+    end
+    def element_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+      else
+        value = slot
+        slot = args.pop
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('element')
+      itemconfigure(id_list, slot, value)
+    end
+    def element_configinfo(id, slot=nil)
+      itemconfiginfo(['element', tagid(id)], slot)
+    end
+    def current_element_configinfo(id, slot=nil)
+      current_itemconfiginfo(['element', tagid(id)], slot)
+    end
+
+    def bar_cget(id, option)
+      itemcget(['bar', tagid(id)], option)
+    end
+    def bar_cget_strict(id, option)
+      itemcget_strict(['bar', tagid(id)], option)
+    end
+    def bar_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+      else
+        value = slot
+        slot = args.pop
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('bar')
+      itemconfigure(id_list, slot, value)
+    end
+    def bar_configinfo(id, slot=nil)
+      itemconfiginfo(['bar', tagid(id)], slot)
+    end
+    def current_bar_configinfo(id, slot=nil)
+      current_itemconfiginfo(['bar', tagid(id)], slot)
+    end
+
+    def line_cget(id, option)
+      itemcget(['line', tagid(id)], option)
+    end
+    def line_cget_strict(id, option)
+      itemcget_strict(['line', tagid(id)], option)
+    end
+    def line_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+      else
+        value = slot
+        slot = args.pop
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('line')
+      itemconfigure(id_list, slot, value)
+    end
+    def line_configinfo(id, slot=nil)
+      itemconfiginfo(['line', tagid(id)], slot)
+    end
+    def current_line_configinfo(id, slot=nil)
+      current_itemconfiginfo(['line', tagid(id)], slot)
+    end
+
+    def gridline_cget(option)
+      itemcget('grid', option)
+    end
+    def gridline_cget_strict(option)
+      itemcget_strict('grid', option)
+    end
+    def gridline_configure(slot, value=None)
+      itemconfigure('grid', slot, value)
+    end
+    def gridline_configinfo(slot=nil)
+      itemconfiginfo('grid', slot)
+    end
+    def current_gridline_configinfo(slot=nil)
+      current_itemconfiginfo('grid', slot)
+    end
+
+    def legend_cget(option)
+      itemcget('legend', option)
+    end
+    def legend_cget_strict(option)
+      itemcget_strict('legend', option)
+    end
+    def legend_configure(slot, value=None)
+      itemconfigure('legend', slot, value)
+    end
+    def legend_configinfo(slot=nil)
+      itemconfiginfo('legend', slot)
+    end
+    def current_legend_configinfo(slot=nil)
+      current_itemconfiginfo('legend', slot)
+    end
+
+    def pen_cget(id, option)
+      itemcget(['pen', tagid(id)], option)
+    end
+    def pen_cget_strict(id, option)
+      itemcget_strict(['pen', tagid(id)], option)
+    end
+    def pen_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+      else
+        value = slot
+        slot = args.pop
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('pen')
+      itemconfigure(id_list, slot, value)
+    end
+    def pen_configinfo(id, slot=nil)
+      itemconfiginfo(['pen', tagid(id)], slot)
+    end
+    def current_pen_configinfo(id, slot=nil)
+      current_itemconfiginfo(['pen', tagid(id)], slot)
+    end
+
+    def postscript_cget(option)
+      itemcget('postscript', option)
+    end
+    def postscript_cget_strict(option)
+      itemcget_strict('postscript', option)
+    end
+    def postscript_configure(slot, value=None)
+      itemconfigure('postscript', slot, value)
+    end
+    def postscript_configinfo(slot=nil)
+      itemconfiginfo('postscript', slot)
+    end
+    def current_postscript_configinfo(slot=nil)
+      current_itemconfiginfo('postscript', slot)
+    end
+
+    def marker_cget(id, option)
+      itemcget(['marker', tagid(id)], option)
+    end
+    def marker_cget_strict(id, option)
+      itemcget_strict(['marker', tagid(id)], option)
+    end
+    def marker_configure(*args)
+      slot = args.pop
+      if slot.kind_of?(Hash)
+        value = None
+      else
+        value = slot
+        slot = args.pop
+      end
+      id_list = args.flatten.collect!{|id| tagid(id)}.unshift('marker')
+      itemconfigure(id_list, slot, value)
+    end
+    def marker_configinfo(id, slot=nil)
+      itemconfiginfo(['marker', tagid(id)], slot)
+    end
+    def current_marker_configinfo(id, slot=nil)
+      current_itemconfiginfo(['marker', tagid(id)], slot)
+    end
+
+    alias __itemcget itemcget
+    alias __itemcget_strict itemcget_strict
+    alias __itemconfiginfo itemconfiginfo
+    alias __current_itemconfiginfo current_itemconfiginfo
+    private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo
+
+    def itemcget_strict(tagOrId, option)
+      ret = __itemcget(tagid(tagOrId), option)
+      if option == 'bindtags' || option == :bindtags
+        ret.collect{|tag| TkBindTag.id2obj(tag)}
+      else
+        ret
+      end
+    end
+    def itemcget(tagOrId, option)
+      unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+        itemcget_strict(tagOrId, option)
+      else
+        begin
+          itemcget_strict(tagOrId, option)
+        rescue => e
+          begin
+            if current_itemconfiginfo(tagOrId).has_key?(option.to_s)
+              # error on known option
+              fail e
+            else
+              # unknown option
+              nil
+            end
+          rescue
+            fail e  # tag error
+          end
+        end
+      end
+    end
+    def itemconfiginfo(tagOrId, slot = nil)
+      ret = __itemconfiginfo(tagid(tagOrId), slot)
+
+      if TkComm::GET_CONFIGINFO_AS_ARRAY
+        if slot
+          if slot == 'bindtags' || slot == :bindtags
+            ret[-2] = ret[-2].collect{|tag| TkBindTag.id2obj(tag)}
+            ret[-1] = ret[-1].collect{|tag| TkBindTag.id2obj(tag)}
+          end
+        else
+          if (inf = ret.assoc('bindtags'))
+            inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+            inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+          end
+        end
+
+      else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+        if (inf = ret['bindtags'])
+          inf[-2] = inf[-2].collect{|tag| TkBindTag.id2obj(tag)}
+          inf[-1] = inf[-1].collect{|tag| TkBindTag.id2obj(tag)}
+          ret['bindtags'] = inf
+        end
+      end
+
+      ret
+    end
+    def current_itemconfiginfo(tagOrId, slot = nil)
+      ret = __current_itemconfiginfo(tagid(tagOrId), slot)
+
+      if (val = ret['bindtags'])
+        ret['bindtags'] = val.collect{|tag| TkBindTag.id2obj(tag)}
+      end
+
+      ret
+    end
+
+    private :itemcget, :itemcget_strict
+    private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
+
+    #################
+
+    class Axis < TkObject
+      (OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint]).instance_eval{
+        @mutex = Mutex.new
+        def mutex; @mutex; end
+        freeze
+      }
+
+      AxisID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        AxisID_TBL.mutex.synchronize{ AxisID_TBL.clear }
+      }
+
+      def self.id2obj(chart, id)
+        cpath = chart.path
+        AxisID_TBL.mutex.synchronize{
+          return id unless AxisID_TBL[cpath]
+          AxisID_TBL[cpath][id]? AxisID_TBL[cpath][id]: id
+        }
+      end
+
+      def self.new(chart, axis=nil, keys={})
+        if axis.kind_of?(Hash)
+          keys = axis
+          axis = nil
+        end
+        if keys
+          keys = _symbolkey2str(keys)
+          not_create = keys.delete('without_creating')
+        else
+          not_create = false
+        end
+
+        obj = nil
+        AxisID_TBL.mutex.synchronize{
+          chart_path = chart.path
+          AxisID_TBL[chart_path] ||= {}
+          if axis && AxisID_TBL[chart_path][axis]
+            obj = AxisID_TBL[chart_path][axis]
+          else
+            (obj = self.allocate).instance_eval{
+              if axis
+                @axis = @id = axis.to_s
+              else
+                OBJ_ID.mutex.synchronize{
+                  @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+                  OBJ_ID[1].succ!
+                }
+              end
+              @path = @id
+              @parent = @chart = chart
+              @cpath = @chart.path
+              Axis::AxisID_TBL[@cpath][@axis] = self
+              unless not_create
+                tk_call(@chart, 'axis', 'create', @axis, keys)
+                return obj
+              end
+            }
+          end
+        }
+
+        obj.configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, axis=nil, keys={})
+        # dummy:: not called by 'new' method
+
+        if axis.kind_of?(Hash)
+          keys = axis
+          axis = nil
+        end
+        if axis
+          @axis = @id = axis.to_s
+        else
+          OBJ_ID.mutex.synchronize{
+            @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+            OBJ_ID[1].succ!
+          }
+        end
+        @path = @id
+        @parent = @chart = chart
+        @cpath = @chart.path
+        # Axis::AxisID_TBL[@cpath][@axis] = self
+        keys = _symbolkey2str(keys)
+        unless keys.delete('without_creating')
+          # @chart.axis_create(@axis, keys)
+          tk_call(@chart, 'axis', 'create', @axis, keys)
+        end
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.axis_cget(@id, option)
+      end
+      def cget_strict(option)
+        @chart.axis_cget_strict(@id, option)
+      end
+      def configure(key, value=None)
+        @chart.axis_configure(@id, key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.axis_configinfo(@id, key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_axis_configinfo(@id, key)
+      end
+
+      def command(cmd=nil, &b)
+        if cmd
+          configure('command', cmd)
+        elsif b
+          configure('command', Proc.new(&b))
+        else
+          cget('command')
+        end
+      end
+
+      def delete
+        @chart.axis_delete(@id)
+        self
+      end
+
+      def invtransform(val)
+        @chart.axis_invtransform(@id, val)
+      end
+
+      def limits
+        @chart.axis_limits(@id)
+      end
+
+      def name
+        @axis
+      end
+        
+      def transform(val)
+        @chart.axis_transform(@id, val)
+      end
+
+      def view
+        @chart.axis_view(@id)
+        self
+      end
+
+      def use(name=None) # if @id == xaxis | x2axis | yaxis | y2axis
+        @chart.axis_use(@id, name)
+      end
+
+      def use_as(axis) # axis := xaxis | x2axis | yaxis | y2axis
+        @chart.axis_use(axis, @id)
+      end
+    end
+
+    #################
+
+    class Crosshairs < TkObject
+      CrosshairsID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear }
+      }
+
+      def self.new(chart, keys={})
+        obj = nil
+        CrosshairsID_TBL.mutex.synchronize{
+          unless (obj = CrosshairsID_TBL[chart.path])
+            (obj = self.allocate).instance_eval{
+              @parent = @chart = chart
+              @cpath = @chart.path
+              @path = @id = 'crosshairs'
+              Crosshairs::CrosshairsID_TBL[@cpath] = self
+            }
+          end
+        }
+        chart.crosshair_configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, keys={})
+        # dummy:: not called by 'new' method
+
+        @parent = @chart = chart
+        @cpath = @chart.path
+        # Crosshairs::CrosshairsID_TBL[@cpath] = self
+        @chart.crosshair_configure(keys) unless keys.empty?
+        @path = @id = 'crosshairs'
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.crosshair_cget(option)
+      end
+      def cget_strict(option)
+        @chart.crosshair_cget_strict(option)
+      end
+      def configure(key, value=None)
+        @chart.crosshair_configure(key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.crosshair_configinfo(key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_crosshair_configinfo(key)
+      end
+
+      def off
+        @chart.crosshair_off
+        self
+      end
+      def on
+        @chart.crosshair_on
+        self
+      end
+      def toggle
+        @chart.crosshair_toggle
+        self
+      end
+    end
+
+    #################
+
+    class Element < TkObject
+      extend Tk
+      extend TkItemFontOptkeys
+      extend TkItemConfigOptkeys
+
+      extend Tk::BLT::PlotComponent::OptKeys
+
+      ElementTypeName = 'element'
+      ElementTypeToClass = { ElementTypeName=>self }
+
+      ElementID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear }
+      }
+
+      (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{
+        @mutex = Mutex.new
+        def mutex; @mutex; end
+        freeze
+      }
+
+      def Element.type2class(type)
+        ElementTypeToClass[type]
+      end
+
+      def Element.id2obj(chart, id)
+        cpath = chart.path
+        ElementID_TBL.mutex.synchronize{
+          return id unless ElementID_TBL[cpath]
+          ElementID_TBL[cpath][id]? ElementID_TBL[cpath][id]: id
+        }
+      end
+
+      def self.new(chart, element=nil, keys={})
+        if element.kind_of?(Hash)
+          keys = element
+          element = nil
+        end
+        if keys
+          keys = _symbolkey2str(keys)
+          not_create = keys.delete('without_creating')
+        else
+          not_create = false
+        end
+
+        obj = nil
+        ElementID_TBL.mutex.synchronize{
+          chart_path = chart.path
+          ElementID_TBL[chart_path] ||= {}
+          if element && ElementID_TBL[chart_path][element]
+            obj = ElementID_TBL[chart_path][element]
+          else
+            (obj = self.allocate).instance_eval{
+              if element
+                @element = @id = element.to_s
+              else
+                OBJ_ID.mutex.synchronize{
+                  @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+                  OBJ_ID[1].succ!
+                }
+              end
+              @path = @id
+              @parent = @chart = chart
+              @cpath = @chart.path
+              @typename = self.class::ElementTypeName
+              Element::ElementID_TBL[@cpath][@element] = self
+              unless not_create
+                tk_call(@chart, @typename, 'create', @element, keys)
+                return obj
+              end
+            }
+          end
+        }
+
+        obj.configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, element=nil, keys={})
+        # dummy:: not called by 'new' method
+
+        if element.kind_of?(Hash)
+          keys = element
+          element = nil
+        end
+        if element
+          @element = @id = element.to_s
+        else
+          OBJ_ID.mutex.synchronize{
+            @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+            OBJ_ID[1].succ!
+          }
+        end
+        @path = @id
+        @parent = @chart = chart
+        @cpath = @chart.path
+        @typename = self.class::ElementTypeName
+        # Element::ElementID_TBL[@cpath][@element] = self
+        keys = _symbolkey2str(keys)
+        unless keys.delete('without_creating')
+          # @chart.element_create(@element, keys)
+          tk_call(@chart, @typename, 'create', @element, keys)
+        end
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        # @chart.element_cget(@id, option)
+        @chart.__send__(@typename + '_cget', @id, option)
+      end
+      def cget_strict(option)
+        @chart.__send__(@typename + '_cget_strict', @id, option)
+      end
+      def configure(key, value=None)
+        # @chart.element_configure(@id, key, value)
+        @chart.__send__(@typename + '_configure', @id, key, value)
+        self
+      end
+      def configinfo(key=nil)
+        # @chart.element_configinfo(@id, key)
+        @chart.__send__(@typename + '_configinfo', @id, key)
+      end
+      def current_configinfo(key=nil)
+        # @chart.current_element_configinfo(@id, key)
+        @chart.__send__('current_' << @typename << '_configinfo', @id, key)
+      end
+
+      def activate(*args)
+        @chart.element_activate(@id, *args)
+      end
+
+      def closest(x, y, var, keys={})
+        # @chart.element_closest(x, y, var, @id, keys)
+        @chart.__send__(@typename + '_closest', x, y, var, @id, keys)
+      end
+
+      def deactivate
+        @chart.element_deactivate(@id)
+        self
+      end
+
+      def delete
+        @chart.element_delete(@id)
+        self
+      end
+
+      def exist?
+        @chart.element_exist?(@id)
+      end
+
+      def name
+        @element
+      end
+
+      def type
+        @chart.element_type(@id)
+      end
+    end
+
+    class Bar < Element
+      ElementTypeName = 'bar'.freeze
+      ElementTypeToClass[ElementTypeName] = self
+    end
+    class Line < Element
+      ElementTypeName = 'line'.freeze
+      ElementTypeToClass[ElementTypeName] = self
+    end
+
+    #################
+
+    class GridLine < TkObject
+      GridLineID_TBL = TkCore::INTERP.create_table
+      TkCore::INTERP.init_ip_env{
+        GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear }
+      }
+
+      def self.new(chart, keys={})
+        obj = nil
+        GridLineID_TBL.mutex.synchronize{
+          unless (obj = GridLineID_TBL[chart.path])
+            (obj = self.allocate).instance_eval{
+              @parent = @chart = chart
+              @cpath = @chart.path
+              @path = @id = 'grid'
+              GridLine::GridLineID_TBL[@cpath] = self
+            }
+          end
+        }
+        chart.gridline_configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, keys={})
+        # dummy:: not called by 'new' method
+
+        @parent = @chart = chart
+        @cpath = @chart.path
+        # GridLine::GridLineID_TBL[@cpath] = self
+        @chart.gridline_configure(keys) unless keys.empty?
+        @path = @id = 'grid'
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.gridline_cget(option)
+      end
+      def cget_strict(option)
+        @chart.gridline_cget_strict(option)
+      end
+      def configure(key, value=None)
+        @chart.gridline_configure(key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.gridline_configinfo(key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_gridline_configinfo(key)
+      end
+
+      def off
+        @chart.gridline_off
+        self
+      end
+      def on
+        @chart.gridline_on
+        self
+      end
+      def toggle
+        @chart.gridline_toggle
+        self
+      end
+    end
+
+    #################
+
+    class Legend < TkObject
+      LegendID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear }
+      }
+
+      def self.new(chart, keys={})
+        obj = nil
+        LegenedID_TBL.mutex.synchronize{
+          unless (obj = LegenedID_TBL[chart.path])
+            (obj = self.allocate).instance_eval{
+              @parent = @chart = chart
+              @cpath = @chart.path
+              @path = @id = 'crosshairs'
+              Legend::LegenedID_TBL[@cpath] = self
+            }
+          end
+        }
+        chart.legend_configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, keys={})
+        # dummy:: not called by 'new' method
+
+        @parent = @chart = chart
+        @cpath = @chart.path
+        # Legend::LegendID_TBL[@cpath] = self
+        @chart.legend_configure(keys) unless keys.empty?
+        @path = @id = 'legend'
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.legend_cget(option)
+      end
+      def cget_strict(option)
+        @chart.legend_cget_strict(option)
+      end
+      def configure(key, value=None)
+        @chart.legend_configure(key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.legend_configinfo(key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_legend_configinfo(key)
+      end
+
+      def activate(*args)
+        @chart.legend_activate(*args)
+      end
+
+      def deactivate(*args)
+        @chart.legend_deactivate(*args)
+      end
+
+      def get(pos, y=nil)
+        @chart.legend_get(pos, y)
+      end
+    end
+
+    #################
+
+    class Pen < TkObject
+      (OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint]).instance_eval{
+        @mutex = Mutex.new
+        def mutex; @mutex; end
+        freeze
+      }
+
+      PenID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        PenID_TBL.mutex.synchronize{ PenID_TBL.clear }
+      }
+
+      def self.id2obj(chart, id)
+        cpath = chart.path
+        PenID_TBL.mutex.synchronize{
+          return id unless PenID_TBL[cpath]
+          PenID_TBL[cpath][id]? PenID_TBL[cpath][id]: id
+        }
+      end
+
+      def self.new(chart, pen=nil, keys={})
+        if pen.kind_of?(Hash)
+          keys = pen
+          pen = nil
+        end
+        if keys
+          keys = _symbolkey2str(keys)
+          not_create = keys.delete('without_creating')
+        else
+          not_create = false
+        end
+
+        obj = nil
+        PenID_TBL.mutex.synchronize{
+          chart_path = chart.path
+          PenID_TBL[chart_path] ||= {}
+          if pen && PenID_TBL[chart_path][pen]
+            obj = PenID_TBL[chart_path][pen]
+          else
+            (obj = self.allocate).instance_eval{
+              if pen
+                @pen = @id = pen.to_s
+              else
+                OBJ_ID.mutex.synchronize{
+                  @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+                  OBJ_ID[1].succ!
+                }
+              end
+              @path = @id
+              @parent = @chart = chart
+              @cpath = @chart.path
+              Pen::PenID_TBL[@cpath][@pen] = self
+              unless not_create
+                tk_call(@chart, 'pen', 'create', @pen, keys)
+                return obj
+              end
+            }
+          end
+        }
+
+        obj.configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, pen=nil, keys={})
+        if pen.kind_of?(Hash)
+          keys = pen
+          pen = nil
+        end
+        if pen
+          @pen = @id = pen.to_s
+        else
+          OBJ_ID.mutex.synchronize{
+            @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+            OBJ_ID[1].succ!
+          }
+        end
+        @path = @id
+        @parent = @chart = chart
+        @cpath = @chart.path
+        Pen::PenID_TBL[@cpath][@pen] = self
+        keys = _symbolkey2str(keys)
+        unless keys.delete('without_creating')
+          # @chart.pen_create(@pen, keys)
+          tk_call(@chart, 'pen', 'create', @pen, keys)
+        end
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.pen_cget(@id, option)
+      end
+      def cget_strict(option)
+        @chart.pen_cget_strict(@id, option)
+      end
+      def configure(key, value=None)
+        @chart.pen_configure(@id, key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.pen_configinfo(@id, key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_pen_configinfo(@id, key)
+      end
+
+      def delete
+        @chart.pen_delete(@id)
+        self
+      end
+
+      def name
+        @pen
+      end
+    end
+
+    #################
+
+    class Postscript < TkObject
+      PostscriptID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear }
+      }
+
+      def self.new(chart, keys={})
+        obj = nil
+        PostscriptID_TBL.mutex.synchronize{
+          unless (obj = PostscriptID_TBL[chart.path])
+            (obj = self.allocate).instance_eval{
+              @parent = @chart = chart
+              @cpath = @chart.path
+              @path = @id = 'postscript'
+              Postscript::PostscriptID_TBL[@cpath] = self
+            }
+          end
+        }
+        chart.postscript_configure(keys) if obj && ! keys.empty?
+        obj
+      end
+
+      def initialize(chart, keys={})
+        # dummy:: not called by 'new' method
+
+        @parent = @chart = chart
+        @cpath = @chart.path
+        # Postscript::PostscriptID_TBL[@cpath] = self
+        @chart.postscript_configure(keys) unless keys.empty?
+        @path = @id = 'postscript'
+      end
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.postscript_cget(option)
+      end
+      def cget_strict(option)
+        @chart.postscript_cget_strict(option)
+      end
+      def configure(key, value=None)
+        @chart.postscript_configure(key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.postscript_configinfo(key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_postscript_configinfo(key)
+      end
+
+      def output(file=nil, keys={})
+        if file.kind_of?(Hash)
+          keys = file
+          file = nil
+        end
+
+        ret = @chart.postscript_output(file, keys)
+
+        if file
+          self
+        else
+          ret
+        end
+      end
+    end
+
+    #################
+    class Marker < TkObject
+      extend Tk
+      extend TkItemFontOptkeys
+      extend TkItemConfigOptkeys
+
+      extend Tk::BLT::PlotComponent::OptKeys
+
+      MarkerTypeName = nil
+      MarkerTypeToClass = {}
+      MarkerID_TBL = TkCore::INTERP.create_table
+
+      TkCore::INTERP.init_ip_env{
+        MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear }
+      }
+
+      def Marker.type2class(type)
+        MarkerTypeToClass[type]
+      end
+
+      def Marker.id2obj(chart, id)
+        cpath = chart.path
+        MarkerID_TBL.mutex.synchronize{
+          if MarkerID_TBL[cpath]
+            MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+          else
+            id
+          end
+        }
+      end
+
+      def self._parse_create_args(keys)
+        fontkeys = {}
+        methodkeys = {}
+        if keys.kind_of? Hash
+          keys = _symbolkey2str(keys)
+
+          __item_font_optkeys(nil).each{|key|
+            fkey = key.to_s
+            fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+            fkey = "kanji#{key}"
+            fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+            fkey = "latin#{key}"
+            fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+
+            fkey = "ascii#{key}"
+            fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
+          }
+
+          __item_optkey_aliases(nil).each{|alias_name, real_name|
+            alias_name = alias_name.to_s
+            if keys.has_key?(alias_name)
+              keys[real_name.to_s] = keys.delete(alias_name)
+            end
+          }
+
+          __item_methodcall_optkeys(nil).each{|key|
+            key = key.to_s
+            methodkeys[key] = keys.delete(key) if keys.key?(key)
+          }
+
+          __item_ruby2val_optkeys(nil).each{|key, method|
+            key = key.to_s
+            keys[key] = method.call(keys[key]) if keys.has_key?(key)
+          }
+
+          args = itemconfig_hash_kv(nil, keys)
+        else
+          args = []
+        end
+
+        [args, fontkeys]
+      end
+      private_class_method :_parse_create_args
+
+      def self.create(chart, keys={})
+        unless self::MarkerTypeName
+          fail RuntimeError, "#{self} is an abstract class"
+        end
+        args, fontkeys = _parse_create_args(keys)
+        idnum = tk_call_without_enc(chart.path, 'marker', 'create', 
+                                    self::MarkerTypeName, *args)
+        chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
+        idnum.to_i  # 'item id' is an integer number
+      end
+
+      def self.create_type(chart, type, keys={})
+        args, fontkeys = _parse_create_args(keys)
+        idnum = tk_call_without_enc(chart.path, 'marker', 'create', 
+                                    type, *args)
+        chart.marker_configure(idnum, fontkeys) unless fontkeys.empty?
+        id = idnum.to_i  # 'item id' is an integer number
+        obj = self.allocate
+        obj.instance_eval{
+          @parent = @chart = chart
+          @cpath = chart.path
+          @id = id
+          Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+            Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+            Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+          }
+        }
+        obj
+      end
+
+      def initialize(parent, *args)
+        @parent = @chart = parent
+        @cpath = parent.path
+
+        @path = @id = create_self(*args) # an integer number as 'item id'
+        Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+          Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+          Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+        }
+      end
+      def create_self(*args)
+        self.class.create(@chart, *args) # return an integer as 'item id'
+      end
+      private :create_self
+
+      def id
+        @id
+      end
+
+      def to_eval
+        @id
+      end
+
+      def cget(option)
+        @chart.marker_cget(@id, option)
+      end
+      def cget_strict(option)
+        @chart.marker_cget_strict(@id, option)
+      end
+      def configure(key, value=None)
+        @chart.marker_configure(@id, key, value)
+        self
+      end
+      def configinfo(key=nil)
+        @chart.marker_configinfo(@id, key)
+      end
+      def current_configinfo(key=nil)
+        @chart.current_marker_configinfo(@id, key)
+      end
+
+      def after(target=None)
+        @chart.marker_after(@id, target)
+      end
+
+      def before(target=None)
+        @chart.marker_before(@id, target)
+      end
+
+      def delete
+        @chart.marker_delete(@id)
+      end
+
+      def exist?
+        @chart.marker_exist(@id)
+      end
+
+      def type
+        @chart.marker_type(@id)
+      end
+    end
+
+    class TextMarker < Marker
+      MarkerTypeName = 'text'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+    class LineMarker < Marker
+      MarkerTypeName = 'line'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+    class BitmapMarker < Marker
+      MarkerTypeName = 'bitmap'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+    class ImageMarker < Marker
+      MarkerTypeName = 'image'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+    class PolygonMarker < Marker
+      MarkerTypeName = 'polygon'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+    class WindowMarker < Marker
+      MarkerTypeName = 'window'.freeze
+      MarkerTypeToClass[MarkerTypeName] = self
+    end
+
+    #################
+
+    def __destroy_hook__
+      Axis::AxisID_TBL.delete(@path)
+      Crosshairs::CrosshairsID_TBL.delete(@path)
+      Element::ElementID_TBL.delete(@path)
+      GridLine::GridLineID_TBL.delete(@path)
+      Legend::LegendID_TBL.delete(@path)
+      Pen::PenID_TBL.delete(@path)
+      Postscript::PostscriptID_TBL.delete(@path)
+      Marker::MarkerID_TBL.delete(@path)
+      super()
+    end
+
+    #################
+
+    def tagid(tag)
+      if tag.kind_of?(Axis) ||
+          tag.kind_of?(Crosshairs) ||
+          tag.kind_of?(Element) ||
+          tag.kind_of?(GridLine) ||
+          tag.kind_of?(Legend) ||
+          tag.kind_of?(Pen) ||
+          tag.kind_of?(Postscript) ||
+          tag.kind_of?(Marker)
+        tag.id
+      else
+        tag  # maybe an Array of configure paramters
+      end
+    end
+
+    def _component_bind(target, tag, context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind([path, target, 'bind', tagid(tag)], context, cmd, *args)
+      self
+    end
+    def _component_bind_append(target, tag, context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind_append([path, target, 'bind', tagid(tag)], context, cmd, *args)
+      self
+    end
+    def _component_bind_remove(target, tag, context)
+      _bind_remove([path, target, 'bind', tagid(tag)], context)
+      self
+    end
+    def _component_bindinfo(target, tag, context=nil)
+      _bindinfo([path, target, 'bind', tagid(tag)], context)
+    end
+    private :_component_bind, :_component_bind_append
+    private :_component_bind_remove, :_component_bindinfo
+
+    def axis_bind(tag, context, *args)
+      _component_bind('axis', tag, context, *args)
+    end
+    def axis_bind_append(tag, context, *args)
+      _component_bind_append('axis', tag, context, *args)
+    end
+    def axis_bind_remove(tag, context)
+      _component_bind_remove('axis', tag, context)
+    end
+    def axis_bindinfo(tag, context=nil)
+      _component_bindinfo('axis', tag, context)
+    end
+
+    def element_bind(tag, context, *args)
+      _component_bind('element', tag, context, *args)
+    end
+    def element_bind_append(tag, context, *args)
+      _component_bind_append('element', tag, context, *args)
+    end
+    def element_bind_remove(tag, context)
+      _component_bind_remove('element', tag, context)
+    end
+    def element_bindinfo(tag, context=nil)
+      _component_bindinfo('element', tag, context)
+    end
+
+    def bar_bind(tag, context, *args)
+      _component_bind('bar', tag, context, *args)
+    end
+    def bar_bind_append(tag, context, *args)
+      _component_bind_append('bar', tag, context, *args)
+    end
+    def bar_bind_remove(tag, context)
+      _component_bind_remove('bar', tag, context)
+    end
+    def bar_bindinfo(tag, context=nil)
+      _component_bindinfo('bar', tag, context)
+    end
+
+    def line_bind(tag, context, *args)
+      _component_bind('line', tag, context, *args)
+    end
+    def line_bind_append(tag, context, *args)
+      _component_bind_append('line', tag, context, *args)
+    end
+    def line_bind_remove(tag, context)
+      _component_bind_remove('line', tag, context)
+    end
+    def line_bindinfo(tag, context=nil)
+      _component_bindinfo('line', tag, context)
+    end
+
+    def legend_bind(tag, context, *args)
+      _component_bind('legend', tag, context, *args)
+    end
+    def legend_bind_append(tag, context, *args)
+      _component_bind_append('legend', tag, context, *args)
+    end
+    def legend_bind_remove(tag, context)
+      _component_bind_remove('legend', tag, context)
+    end
+    def legend_bindinfo(tag, context=nil)
+      _component_bindinfo('legend', tag, context)
+    end
+
+    def marker_bind(tag, context, *args)
+      _component_bind('marker', tag, context, *args)
+    end
+    def marker_bind_append(tag, context, *args)
+      _component_bind_append('marker', tag, context, *args)
+    end
+    def marker_bind_remove(tag, context)
+      _component_bind_remove('marker', tag, context)
+    end
+    def marker_bindinfo(tag, context=nil)
+      _component_bindinfo('marker', tag, context)
+    end
+
+    ###################
+
+    def axis_create(id=nil, keys={})
+      # tk_send('axis', 'create', tagid(id), keys)
+      Tk::BLT::PlotComponent::Axis.new(self, tagid(id), keys)
+    end
+    def axis_delete(*ids)
+      tk_send('axis', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def axis_invtransform(id, val)
+      list(tk_send('axis', 'invtransform', tagid(id), val))
+    end
+    def axis_limits(id)
+      list(tk_send('axis', 'limits', tagid(id)))
+    end
+    def axis_names(*pats)
+      simplelist(tk_send('axis', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|axis|
+        Tk::BLT::PlotComponent::Axis.id2obj(self, axis)
+      }
+    end
+    def axis_transform(id, val)
+      list(tk_send('axis', 'transform', tagid(id), val))
+    end
+    def axis_view(id)
+      tk_send('axis', 'view', tagid(id))
+      self
+    end
+    def axis_use(id, target=nil)
+      if target
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('axis', 'use', 
+                                                    tagid(id), tagid(target)))
+      else
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('axis', 'use', tagid(id)))
+      end
+    end
+
+    ###################
+
+    def crosshairs_off
+      tk_send_without_enc('crosshairs', 'off')
+      self
+    end
+    def crosshairs_on
+      tk_send_without_enc('crosshairs', 'on')
+      self
+    end
+    def crosshairs_toggle
+      tk_send_without_enc('crosshairs', 'toggle')
+      self
+    end
+
+    ###################
+
+    def element_create(id=nil, keys={})
+      # tk_send('element', 'create', tagid(id), keys)
+      Tk::BLT::PlotComponent::Element.new(self, tagid(id), keys)
+    end
+    def element_activate(*args)
+      if args.empty?
+        list(tk_send('element', 'activate')).collect{|elem|
+          Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+        }
+      else
+        # id, *indices
+        id = args.shift
+        tk_send('element', 'activate', tagid(id), *args)
+      end
+    end
+    def element_closest(x, y, var, *args)
+      if args[-1].kind_of?(Hash)
+        keys = args.pop
+        bool(tk_send('element', 'closest', x, y, var, 
+                     *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+      else
+        bool(tk_send('element', 'closest', x, y, var, 
+                     *(args.collect{|id| tagid(id)})))
+      end
+    end
+    def element_deactivate(*ids)
+      tk_send('element', 'deactivate', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def element_delete(*ids)
+      tk_send('element', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def element_exist?(id)
+      bool(tk_send('element', 'exists', tagid(id)))
+    end
+    def element_names(*pats)
+      simplelist(tk_send('element', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+        Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+      }
+    end
+    def element_show(*names)
+      if names.empty?
+        simplelist(tk_send('element', 'show'))
+      else
+        tk_send('element', 'show', *(names.collect{|n| tagid(n)}))
+        self
+      end
+    end
+    def element_type(id)
+      tk_send('element', 'type', tagid(id))
+    end
+
+    ###################
+
+    def bar_create(id=nil, keys={})
+      # tk_send('bar', 'create', tagid(id), keys)
+      Tk::BLT::PlotComponent::Bar.new(self, tagid(id), keys)
+    end
+    alias bar bar_create
+    def bar_activate(*args)
+      if args.empty?
+        list(tk_send('bar', 'activate')).collect{|elem|
+          Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+        }
+      else
+        # id, *indices
+        id = args.shift
+        tk_send('bar', 'activate', tagid(id), *args)
+      end
+    end
+    def bar_closest(x, y, var, *args)
+      if args[-1].kind_of?(Hash)
+        keys = args.pop
+        bool(tk_send('bar', 'closest', x, y, var, 
+                     *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+      else
+        bool(tk_send('bar', 'closest', x, y, var, 
+                     *(args.collect{|id| tagid(id)})))
+      end
+    end
+    def bar_deactivate(*ids)
+      tk_send('bar', 'deactivate', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def bar_delete(*ids)
+      tk_send('bar', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def bar_exist?(id)
+      bool(tk_send('bar', 'exists', tagid(id)))
+    end
+    def bar_names(*pats)
+      simplelist(tk_send('bar', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+        Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+      }
+    end
+    def bar_show(*names)
+      if names.empty?
+        simplelist(tk_send('bar', 'show'))
+      else
+        tk_send('bar', 'show', *(names.collect{|n| tagid(n)}))
+        self
+      end
+    end
+    def bar_type(id)
+      tk_send('bar', 'type', tagid(id))
+    end
+
+    ###################
+
+    def line_create(id=nil, keys={})
+      # tk_send('line', 'create', tagid(id), keys)
+      Tk::BLT::PlotComponent::Line.new(self, tagid(id), keys)
+    end
+    alias bar line_create
+    def line_activate(*args)
+      if args.empty?
+        list(tk_send('line', 'activate')).collect{|elem|
+          Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+        }
+      else
+        # id, *indices
+        id = args.shift
+        tk_send('line', 'activate', tagid(id), *args)
+      end
+    end
+    def line_closest(x, y, var, *args)
+      if args[-1].kind_of?(Hash)
+        keys = args.pop
+        bool(tk_send('line', 'closest', x, y, var, 
+                     *(hash_kv(keys).concat(args.collect{|id| tagid(id)}))))
+      else
+        bool(tk_send('line', 'closest', x, y, var, 
+                     *(args.collect{|id| tagid(id)})))
+      end
+    end
+    def line_deactivate(*ids)
+      tk_send('line', 'deactivate', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def line_delete(*ids)
+      tk_send('line', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def line_exist?(id)
+      bool(tk_send('line', 'exists', tagid(id)))
+    end
+    def line_names(*pats)
+      simplelist(tk_send('line', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+        Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+      }
+    end
+    def line_show(*names)
+      if names.empty?
+        simplelist(tk_send('line', 'show'))
+      else
+        tk_send('line', 'show', *(names.collect{|n| tagid(n)}))
+        self
+      end
+    end
+    def line_type(id)
+      tk_send('line', 'type', tagid(id))
+    end
+
+    ###################
+
+    def gridline_off
+      tk_send_without_enc('grid', 'off')
+      self
+    end
+    def gridline_on
+      tk_send_without_enc('grid', 'on')
+      self
+    end
+    def gridline_toggle
+      tk_send_without_enc('grid', 'toggle')
+      self
+    end
+
+    ###################
+
+    def legend_window_create(parent=nil, keys=nil)
+      if parent.kind_of?(Hash)
+        keys = _symbolkey2str(parent)
+        parent = keys.delete('parent')
+        widgetname = keys.delete('widgetname')
+        keys.delete('without_creating')
+      elsif keys
+        keys = _symbolkey2str(keys)
+        widgetname = keys.delete('widgetname')
+        keys.delete('without_creating')
+      end
+
+      legend = self.class.new(parent, :without_creating=>true, 
+                              :widgetname=>widgetname)
+      class << legend
+        def __destroy_hook__
+          TkCore::INTERP.tk_windows.delete(@path)
+        end
+      end
+
+      if keys
+        self.legend_configure(keys.update('position'=>legend))
+      else
+        self.legend_configure('position'=>legend)
+      end
+      legend
+    end
+
+    def legend_activate(*pats)
+      list(tk_send('legend', 'activate', 
+                   *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+        Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+      }
+    end
+    def legend_deactivate(*pats)
+      list(tk_send('legend', 'deactivate', 
+                   *(pats.collect{|pat| tagid(pat)}))).collect{|elem|
+        Tk::BLT::PlotComponent::Element.id2obj(self, elem)
+      }
+    end
+    def legend_get(pos, y=nil)
+      if y
+        Tk::BLT::PlotComponent::Element.id2obj(self, 
+                                               tk_send('legend', 'get', 
+                                                       _at(pos, y)))
+      else
+        Tk::BLT::PlotComponent::Element.id2obj(self, 
+                                               tk_send('legend', 'get', pos))
+      end
+    end
+
+    ###################
+
+    def pen_create(id=nil, keys={})
+      # tk_send('pen', 'create', tagid(id), keys)
+      Tk::BLT::PlotComponent::Pen.new(self, tagid(id), keys)
+    end
+    def pen_delete(*ids)
+      tk_send('pen', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def pen_names(*pats)
+      simplelist(tk_send('pen', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|pen|
+        Tk::BLT::PlotComponent::Pen.id2obj(self, pen)
+      }
+    end
+
+    ###################
+
+    def postscript_output(file=nil, keys={})
+      if file.kind_of?(Hash)
+        keys = file
+        file = nil
+      end
+
+      if file
+        tk_send('postscript', 'output', file, keys)
+        self
+      else
+        tk_send('postscript', 'output', keys)
+      end
+    end
+
+    ###################
+
+    def marker_create(type, keys={})
+      case type
+      when :text, 'text'
+        Tk::BLT::PlotComponent::TextMarker.new(self, keys)
+      when :line, 'line'
+        Tk::BLT::PlotComponent::LineMarker.new(self, keys)
+      when :bitmap, 'bitmap'
+        Tk::BLT::PlotComponent::BitmapMarker.new(self, keys)
+      when :image, 'image'
+        Tk::BLT::PlotComponent::ImageMarker.new(self, keys)
+      when :polygon, 'polygon'
+        Tk::BLT::PlotComponent::PolygonMarker.new(self, keys)
+      when :window, 'window'
+        Tk::BLT::PlotComponent::WindowMarker.new(self, keys)
+      else
+        if type.kind_of?(Tk::BLT::PlotComponent::Marker)
+          type.new(self, keys)
+        else
+          Tk::BLT::PlotComponent::Marker.create_type(self, type, keys)
+        end
+      end
+    end
+    def marker_after(id, target=nil)
+      if target
+        tk_send_without_enc('marker', 'after', tagid(id), tagid(target))
+      else
+        tk_send_without_enc('marker', 'after', tagid(id))
+      end
+      self
+    end
+    def marker_before(id, target=None)
+      if target
+        tk_send_without_enc('marker', 'before', tagid(id), tagid(target))
+      else
+        tk_send_without_enc('marker', 'before', tagid(id))
+      end
+      self
+    end
+    def marker_delete(*ids)
+      tk_send('marker', 'delete', *(ids.collect{|id| tagid(id)}))
+      self
+    end
+    def marker_exist?(id)
+      bool(tk_send('marker', 'exists', tagid(id)))
+    end
+    def marker_names(*pats)
+      simplelist(tk_send('marker', 'names', 
+                         *(pats.collect{|pat| tagid(pat)}))).collect{|id|
+        Tk::BLT::PlotComponent::Marker.id2obj(self, id)
+      }
+    end
+    def marker_type(id)
+      tk_send('marker', 'type', tagid(id))
+    end
+
+    ###################
+
+    def xaxis_cget(option)
+      itemcget('xaxis', option)
+    end
+    def xaxis_cget_strict(option)
+      itemcget_strict('xaxis', option)
+    end
+    def xaxis_configure(slot, value=None)
+      if slot.kind_of?(Hash)
+        slot = _symbolkey2str(slot)
+        if cmd = slot.delete('command')
+          slot['command'] = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      elsif slot == :command || slot == 'command'
+        cmd = value
+        value = proc{|w, tick| 
+          cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+        }
+      end
+      itemconfigure('xaxis', slot, value)
+    end
+    def xaxis_configinfo(slot=nil)
+      itemconfiginfo('xaxis', slot)
+    end
+    def current_xaxis_configinfo(slot=nil)
+      current_itemconfiginfo('xaxis', slot)
+    end
+    def xaxis_bind(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind([path, 'xaxis', 'bind'], context, cmd, *args)
+      self
+    end
+    def xaxis_bind_append(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind_append([path, 'xaxis', 'bind'], context, cmd, *args)
+      self
+    end
+    def xaxis_bind_remove(context)
+      _bind_remove([path, 'xaxis', 'bind'], context)
+      self
+    end
+    def xaxis_bindinfo(context=nil)
+      _bindinfo([path, 'xaxis', 'bind'], context)
+    end
+    def xaxis_invtransform(val)
+      list(tk_send('xaxis', 'invtransform', val))
+    end
+    def xaxis_limits
+      list(tk_send('xaxis', 'limits'))
+    end
+    def xaxis_transform(val)
+      list(tk_send('xaxis', 'transform', val))
+    end
+    def xaxis_use(target=nil)
+      if target
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('xaxis', 'use', 
+                                                    tagid(target)))
+      else
+        Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('xaxis', 'use'))
+      end
+    end
+
+    def x2axis_cget(option)
+      itemcget('x2axis', option)
+    end
+    def x2axis_cget_strict(option)
+      itemcget_strict('x2axis', option)
+    end
+    def x2axis_configure(slot, value=None)
+      if slot.kind_of?(Hash)
+        slot = _symbolkey2str(slot)
+        if cmd = slot.delete('command')
+          slot['command'] = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      elsif slot == :command || slot == 'command'
+        cmd = value
+        value = proc{|w, tick| 
+          cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+        }
+      end
+      itemconfigure('x2axis', slot, value)
+    end
+    def x2axis_configinfo(slot=nil)
+      itemconfiginfo('x2axis', slot)
+    end
+    def current_x2axis_configinfo(slot=nil)
+      current_itemconfiginfo('x2axis', slot)
+    end
+    def x2axis_bind(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind([path, 'x2axis', 'bind'], context, cmd, *args)
+      self
+    end
+    def x2axis_bind_append(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind_append([path, 'x2axis', 'bind'], context, cmd, *args)
+      self
+    end
+    def x2axis_bind_remove(context)
+      _bind_remove([path, 'x2axis', 'bind'], context)
+      self
+    end
+    def x2axis_bindinfo(context=nil)
+      _bindinfo([path, 'x2axis', 'bind'], context)
+    end
+    def x2axis_invtransform(val)
+      list(tk_send('x2axis', 'invtransform', val))
+    end
+    def x2axis_limits
+      list(tk_send('x2axis', 'limits'))
+    end
+    def x2axis_transform(val)
+      list(tk_send('x2axis', 'transform', val))
+    end
+    def x2axis_use(target=nil)
+      if target
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('x2axis', 'use', 
+                                                    tagid(target)))
+      else
+        Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('x2axis', 'use'))
+      end
+    end
+
+    def yaxis_cget(option)
+      itemcget('yaxis', option)
+    end
+    def yaxis_cget_strict(option)
+      itemcget_strict('yaxis', option)
+    end
+    def yaxis_configure(slot, value=None)
+      if slot.kind_of?(Hash)
+        slot = _symbolkey2str(slot)
+        if cmd = slot.delete('command')
+          slot['command'] = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      elsif slot == :command || slot == 'command'
+        cmd = value
+        value = proc{|w, tick| 
+          cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+        }
+      end
+      itemconfigure('yaxis', slot, value)
+    end
+    def yaxis_configinfo(slot=nil)
+      itemconfiginfo('yaxis', slot)
+    end
+    def current_yaxis_configinfo(slot=nil)
+      current_itemconfiginfo('yaxis', slot)
+    end
+    def yaxis_bind(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind([path, 'yaxis', 'bind'], context, cmd, *args)
+      self
+    end
+    def yaxis_bind_append(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind_append([path, 'yaxis', 'bind'], context, cmd, *args)
+      self
+    end
+    def yaxis_bind_remove(context)
+      _bind_remove([path, 'yaxis', 'bind'], context)
+      self
+    end
+    def yaxis_bindinfo(context=nil)
+      _bindinfo([path, 'yaxis', 'bind'], context)
+    end
+    def yaxis_invtransform(val)
+      list(tk_send('yaxis', 'invtransform', val))
+    end
+    def yaxis_limits
+      list(tk_send('yaxis', 'limits'))
+    end
+    def yaxis_transform(val)
+      list(tk_send('yaxis', 'transform', val))
+    end
+    def yaxis_use(target=nil)
+      if target
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('yaxis', 'use', 
+                                                    tagid(target)))
+      else
+        Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('yaxis', 'use'))
+      end
+    end
+
+    def y2axis_cget(option)
+      itemcget('y2axis', option)
+    end
+    def y2axis_cget_strict(option)
+      itemcget_strict('y2axis', option)
+    end
+    def y2axis_configure(slot, value=None)
+      if slot.kind_of?(Hash)
+        slot = _symbolkey2str(slot)
+        if cmd = slot.delete('command')
+          slot['command'] = proc{|w, tick| 
+            cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+          }
+        end
+      elsif slot == :command || slot == 'command'
+        cmd = value
+        value = proc{|w, tick| 
+          cmd.call(TkComm.window(w), TkComm.num_or_str(tick))
+        }
+      end
+      itemconfigure('y2axis', slot, value)
+    end
+    def y2axis_configinfo(slot=nil)
+      axis_configinfo('y2axis', slot)
+    end
+    def current_y2axis_configinfo(slot=nil)
+      current_itemconfiginfo('y2axis', slot)
+    end
+    def y2axis_bind(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind([path, 'y2axis', 'bind'], context, cmd, *args)
+      self
+    end
+    def y2axis_bind_append(context, *args)
+      if TkComm._callback_entry?(args[0]) || !block_given?
+        cmd = args.shift
+      else
+        cmd = Proc.new
+      end
+      _bind_append([path, 'y2axis', 'bind'], context, cmd, *args)
+      self
+    end
+    def y2axis_bind_remove(context)
+      _bind_remove([path, 'y2axis', 'bind'], context)
+      self
+    end
+    def y2axis_bindinfo(context=nil)
+      _bindinfo([path, 'y2axis', 'bind'], context)
+    end
+    def y2axis_invtransform(val)
+      list(tk_send('y2axis', 'invtransform', val))
+    end
+    def y2axis_limits
+      list(tk_send('y2axis', 'limits'))
+    end
+    def y2axis_transform(val)
+      list(tk_send('y2axis', 'transform', val))
+    end
+    def y2axis_use(target=nil)
+      if target
+        Tk::BLT::PlotComponent::Axis.id2obj(self, 
+                                            tk_send('y2axis', 'use', 
+                                                    tagid(target)))
+      else
+        Tk::BLT::PlotComponent::Axis.id2obj(self, tk_send('y2axis', 'use'))
+      end
+    end
+  end
+end