From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb | 1404 ++++++++++++++++++++++ 1 file changed, 1404 insertions(+) create mode 100644 jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb (limited to 'jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb') diff --git a/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb new file mode 100644 index 0000000..a1ebe86 --- /dev/null +++ b/jni/ruby/ext/tk/lib/tkextlib/tcllib/plotchart.rb @@ -0,0 +1,1404 @@ +# +# tkextlib/tcllib/plotchart.rb +# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) +# +# * Part of tcllib extension +# * Simple plotting and charting package +# +# (The following is the original description of the library.) +# +# Plotchart is a Tcl-only package that focuses on the easy creation of +# xy-plots, barcharts and other common types of graphical presentations. +# The emphasis is on ease of use, rather than flexibility. The procedures +# that create a plot use the entire canvas window, making the layout of the +# plot completely automatic. +# +# This results in the creation of an xy-plot in, say, ten lines of code: +# -------------------------------------------------------------------- +# package require Plotchart +# +# canvas .c -background white -width 400 -height 200 +# pack .c -fill both +# +# # +# # Create the plot with its x- and y-axes +# # +# set s [::Plotchart::createXYPlot .c {0.0 100.0 10.0} {0.0 100.0 20.0}] +# +# foreach {x y} {0.0 32.0 10.0 50.0 25.0 60.0 78.0 11.0 } { +# $s plot series1 $x $y +# } +# +# $s title "Data series" +# -------------------------------------------------------------------- +# +# A drawback of the package might be that it does not do any data management. +# So if the canvas that holds the plot is to be resized, the whole plot must +# be redrawn. The advantage, though, is that it offers a number of plot and +# chart types: +# +# * XY-plots like the one shown above with any number of data series. +# * Stripcharts, a kind of XY-plots where the horizontal axis is adjusted +# automatically. The result is a kind of sliding window on the data +# series. +# * Polar plots, where the coordinates are polar instead of cartesian. +# * Isometric plots, where the scale of the coordinates in the two +# directions is always the same, i.e. a circle in world coordinates +# appears as a circle on the screen. +# You can zoom in and out, as well as pan with these plots (Note: this +# works best if no axes are drawn, the zooming and panning routines do +# not distinguish the axes), using the mouse buttons with the control +# key and the arrow keys with the control key. +# * Piecharts, with automatic scaling to indicate the proportions. +# * Barcharts, with either vertical or horizontal bars, stacked bars or +# bars side by side. +# * Timecharts, where bars indicate a time period and milestones or other +# important moments in time are represented by triangles. +# * 3D plots (both for displaying surfaces and 3D bars) +# + +require 'tk' +require 'tkextlib/tcllib.rb' + +# TkPackage.require('Plotchart', '0.9') +# TkPackage.require('Plotchart', '1.1') +# TkPackage.require('Plotchart', '1.6.3') +TkPackage.require('Plotchart') + +module Tk + module Tcllib + module Plotchart + PACKAGE_NAME = 'Plotchart'.freeze + def self.package_name + PACKAGE_NAME + end + + def self.package_version + begin + TkPackage.require('Plotchart') + rescue + '' + end + end + end + end +end + +module Tk::Tcllib::Plotchart + extend TkCore + ############################ + def self.view_port(w, *args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', w.path, *(args.flatten)) + end + + def self.world_coordinates(w, *args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + w.path, *(args.flatten)) + end + + def self.world_3D_coordinates(w, *args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + w.path, *(args.flatten)) + end + + def self.coords_to_pixel(w, x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', w.path, x, y)) + end + + def self.coords_3D_to_pixel(w, x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', w.path, x, y, z)) + end + + def self.plotconfig(*args) + case args.length + when 0, 1, 2 + # 0: (no args) --> list of chat types + # 1: charttype --> list of components + # 2: charttype, component --> list of properties + simplelist(tk_call('::Plotchart::plotconfig', *args)) + when 3 + # 3: charttype, component, property --> current value + tk_call('::Plotchart::plotconfig', *args) + else + # 4: charttype, component, property, value : set new value + # 5+: Error on Tcl/Tk + tk_call('::Plotchart::plotconfig', *args) + nil + end + end + + def self.plotpack(w, dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', w.path, dir, *plots) + w + end + + def self.polar_coordinates(w, radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', w.path, radmax) + end + + def self.polar_to_pixel(w, rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', w.path, rad, phi)) + end + + def self.pixel_to_coords(w, x, y) + list(tk_call_without_enc('::Plotchart::pixelToCoords', w.path, x, y)) + end + + def self.determine_scale(*args) # (xmin, xmax, inverted=false) + tk_call_without_enc('::Plotchart::determineScale', *args) + end + + def self.set_zoom_pan(w) + tk_call_without_enc('::Plotchart::setZoomPan', w.path) + end + + ############################ + module ChartMethod + include TkCore + + def title(str) + tk_call_without_enc(@chart, 'title', _get_eval_enc_str(str)) + self + end + + def save_plot(filename) + tk_call_without_enc(@chart, 'saveplot', filename) + self + end + + def xtext(str) + tk_call_without_enc(@chart, 'xtext', _get_eval_enc_str(str)) + self + end + + def ytext(str) + tk_call_without_enc(@chart, 'ytext', _get_eval_enc_str(str)) + self + end + + def xconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'xconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'xconfig', "-#{key}",value) + end + self + end + + def yconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'yconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'yconfig', "-#{key}", value) + end + self + end + + def background(part, color_or_image, dir) + tk_call_without_enc(@chart, 'background', + part, color_or_image, dir) + self + end + + def xticklines(color=None) + tk_call(@chart, 'xticklines', color) + self + end + + def yticklines(color=None) + tk_call(@chart, 'yticklines', color) + self + end + + def legendconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'legendconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'legendconfig', "-#{key}", value) + end + self + end + + def legend(series, text) + tk_call_without_enc(@chart, 'legend', + _get_eval_enc_str(series), _get_eval_enc_str(text)) + self + end + + def balloon(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift + end + + text, dir = args + + tk_call_without_enc(@chart, 'balloon', x, y, + _get_eval_enc_str(text), dir) + self + end + + def balloonconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'balloonconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'balloonconfig', "-#{key}", value) + end + end + + def plaintext(*args) # args => (x, y, text, dir) or ([x, y], text, dir) + if args[0].kind_of?(Array) + # args => ([x, y], text, dir) + x, y = args.shift + else + # args => (x, y, text, dir) + x = args.shift + y = args.shift + end + + text, dir = args + + tk_call_without_enc(@chart, 'plaintext', x, y, + _get_eval_enc_str(text), dir) + self + end + + ############################ + + def view_port(*args) # args := pxmin, pymin, pxmax, pymax + tk_call_without_enc('::Plotchart::viewPort', @path, *(args.flatten)) + self + end + + def world_coordinates(*args) # args := xmin, ymin, xmax, ymax + tk_call_without_enc('::Plotchart::worldCoordinates', + @path, *(args.flatten)) + self + end + + def world_3D_coordinates(*args) + # args := xmin, ymin, zmin, xmax, ymax, zmax + tk_call_without_enc('::Plotchart::world3DCoordinates', + @path, *(args.flatten)) + self + end + + def coords_to_pixel(x, y) + list(tk_call_without_enc('::Plotchart::coordsToPixel', @path, x, y)) + end + + def coords_3D_to_pixel(x, y, z) + list(tk_call_without_enc('::Plotchart::coords3DToPixel', @path, x, y, z)) + end + + def plotpack(dir, *plots) + tk_call_without_enc('::Plotchart::plotpack', @path, dir, *plots) + self + end + + def polar_coordinates(radmax) + tk_call_without_enc('::Plotchart::polarCoordinates', @path, radmax) + self + end + + def polar_to_pixel(rad, phi) + list(tk_call_without_enc('::Plotchart::polarToPixel', @path, rad, phi)) + end + + def pixel_to_coords(x, y) + list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) + end + + def determine_scale(xmax, ymax) + tk_call_without_enc('::Plotchart::determineScale', @path, xmax, ymax) + self + end + + def set_zoom_pan() + tk_call_without_enc('::Plotchart::setZoomPan', @path) + self + end + end + + ############################ + class XYPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createXYPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, x, y) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), x, y) + self + end + + def contourlines(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourlines', xcrd, ycrd, vals, clss) + self + end + + def contourfill(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourfill', xcrd, ycrd, vals, clss) + self + end + + def contourbox(xcrd, ycrd, vals, clss=None) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + vals = array2tk_list(vals) if vals.kind_of?(Array) + clss = array2tk_list(clss) if clss.kind_of?(Array) + + tk_call(@chart, 'contourbox', xcrd, ycrd, vals, clss) + self + end + + def color_map(colors) + colors = array2tk_list(colors) if colors.kind_of?(Array) + + tk_call_without_enc(@chart, 'colorMap', colors) + self + end + + def grid_cells(xcrd, ycrd) + xcrd = array2tk_list(xcrd) if xcrd.kind_of?(Array) + ycrd = array2tk_list(ycrd) if ycrd.kind_of?(Array) + + tk_call_without_enc(@chart, 'grid', xcrd, ycrd) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', series, *hash_kv(key, true)) + else + tk_call(@chart, 'dataconfig', series, "-#{key}", value) + end + end + + def rescale(xscale, yscale) # xscale|yscale => [newmin, newmax, newstep] + tk_call_without_enc(@chart, 'rescale', xscale, yscale) + self + end + + def trend(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'trend', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def rchart(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'rchart', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + + def interval(series, xcrd, ymin, ymax, ycenter=None) + tk_call(@chart, 'interval', series, xcrd, ymin, ymax, ycenter) + self + end + + def box_and_whiskers(series, xcrd, ycrd) + tk_call_without_enc(@chart, 'box-and-whiskers', + _get_eval_enc_str(series), xcrd, ycrd) + self + end + alias box_whiskers box_and_whiskers + + def vectorconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'vectorconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'vectorconfig', series, "-#{key}", value) + end + self + end + + def vector(series, xcrd, ycrd, ucmp, vcmp) + tk_call_without_enc(@chart, 'vector', _get_eval_enc_str(series), + xcrd, ycrd, ucmp, vcmp) + self + end + + def dotconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dotconfig', + _get_eval_enc_str(series), *hash_kv(key, true)) + else + tk_call(@chart, 'dotconfig', series, "-#{key}", value) + end + self + end + + def dot(series, xcrd, ycrd, value) + tk_call_without_enc(@chart, 'dot', _get_eval_enc_str(series), + xcrd, ycrd, value) + self + end + end + + ############################ + class Stripchart < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createStripchart'.freeze + ].freeze + end + + ############################ + class TXPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createTXPlot'.freeze + ].freeze + end + + ############################ + class XLogYPlot < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createXLogYPlot'.freeze + ].freeze + end + + ############################ + class Histogram < XYPlot + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createHistogram'.freeze + ].freeze + end + + ############################ + class PolarPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createPolarplot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] radius_data [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @radius_data = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @radius_data = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@radius_data)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, radius, angle) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(series), + radius, angle) + self + end + + def dataconfig(series, key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'dataconfig', _get_eval_enc_str(series), + *hash_kv(key, true)) + else + tk_call(@chart, 'dataconfig', series, "-#{key}", value) + end + end + end + Polarplot = PolarPlot + + ############################ + class IsometricPlot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createIsometricPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, [, step] [, keys]) + # xaxis := Array of [minimum, maximum] + # yaxis := Array of [minimum, maximum] + # step := Float of stepsize | "noaxes" | :noaxes + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + + if args[0].kind_of?(Hash) + @stepsize = :noaxes + else + @stepsize = args.shift + end + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@yaxis), + @stepsize) + end + private :_create_chart + + def plot(type, *args) + self.__send__("plot_#{type.to_s.tr('-', '_')}", *args) + end + + def plot_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'rectangle', *(args.flatten)) + self + end + + def plot_filled_rectangle(*args) # args := x1, y1, x2, y2, color + tk_call_without_enc(@chart, 'plot', 'filled-rectangle', *(args.flatten)) + self + end + + def plot_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'circle', *(args.flatten)) + self + end + + def plot_filled_circle(*args) # args := xc, yc, radius, color + tk_call_without_enc(@chart, 'plot', 'filled-circle', *(args.flatten)) + self + end + end + Isometricplot = IsometricPlot + + ############################ + class Plot3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DPlot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, yaxis, zaxis [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def plot_function(cmd=Proc.new) + Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}") + tk_call_without_enc(@chart, 'plotfunc', "#{@path}_#{@chart}") + self + end + + def plot_funcont(conts, cmd=Proc.new) + conts = array2tk_list(conts) if conts.kind_of?(Array) + Tk.ip_eval("proc #{@path}_#{@chart} {x y} {#{install_cmd(cmd)} $x $y}") + tk_call_without_enc(@chart, 'plotfuncont', "#{@path}_#{@chart}", conts) + self + end + + def grid_size(nxcells, nycells) + tk_call_without_enc(@chart, 'gridsize', nxcells, nycells) + self + end + + def plot_line(dat, color) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotline', dat, color) + self + end + + def plot_data(dat) + # dat has to be provided as a 2 level array. + # 1st level contains rows, drawn in y-direction, + # and each row is an array whose elements are drawn in x-direction, + # for the columns. + tk_call_without_enc(@chart, 'plotdata', dat) + self + end + + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig', "-#{key}", value) + end + self + end + + def colour(fill, border) + # configure the colours to use for polygon borders and inner area + tk_call_without_enc(@chart, 'colour', fill, border) + self + end + alias colours colour + alias colors colour + alias color colour + end + + ############################ + class Barchart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DBarchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis, nobars [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + # nobars := number of bars + if args[0].kind_of?(Array) + @yaxis = args.shift + @nobars = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + @nobars = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis), @nobars) + end + private :_create_chart + + def plot(label, yvalue, color) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(label), + _get_eval_enc_str(yvalue), color) + self + end + + def config(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'config', *hash_kv(key, true)) + else + tk_call(@chart, 'config', "-#{key}", value) + end + self + end + end + + ############################ + class RibbonChart3D < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::create3DRibbonChart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, yaxis, zaxis [, keys]) + # names := Array of the series + # yaxis := Array of [minimum, maximum, stepsize] + # zaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @yaxis = args.shift + @zaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), + array2tk_list(@yaxis), + array2tk_list(@zaxis)) + end + private :_create_chart + + def line(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'line', xypairs, color) + self + end + + def area(*args) # xypairs, color + color = args.pop # last argument is a color + xypairs = TkComm.slice_ary(args.flatten, 2) # regenerate xypairs + tk_call_without_enc(@chart, 'area', xypairs, color) + self + end + + def zconfig(key, value=None) + if key.kind_of?(Hash) + tk_call_without_enc(@chart, 'zconfig', *hash_kv(key, true)) + else + tk_call(@chart, 'zconfig',"-#{key}", value) + end + self + end + end + + + ############################ + class Piechart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createPiechart'.freeze + ].freeze + + def initialize(*args) # args := ([parent] [, keys]) + if args[0].kind_of?(Tk::Canvas) + parent = args.shift + @path = parent.path + else + super(*args) # create canvas widget + end + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path) + end + private :_create_chart + + def plot(*dat) # argument is a list of [label, value] + tk_call(@chart, 'plot', dat.flatten) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) + self + end + alias colors colours + end + + + ############################ + class Radialchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRadialchart'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] names, scale, style [, keys]) + # radius_data := Array of [maximum_radius, stepsize] + if args[0].kind_of?(Array) + @names = args.shift + @scale = args.shift + @style = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @names = args.shift + @scale = args.shift + @style = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@names), @scale, @style) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(data, color, thickness) + tk_call_without_enc(@chart, 'plot', _get_eval_enc_str(data), + color, thickness) + self + end + + def colours(*list) + tk_call_without_enc(@chart, 'colours', *list) + self + end + alias colors colours + end + + ############################ + class Barchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createBarchart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] xlabels, ylabels [, series] [, keys]) + # xlabels, ylabels := labels | axis ( depend on normal or horizontal ) + # labels := Array of [label, label, ...] + # (It determines the number of bars that will be plotted per series.) + # axis := Array of [minimum, maximum, stepsize] + # series := Integer number of data series | 'stacked' | :stacked + if args[0].kind_of?(Array) + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + super(*args) # create canvas widget + else + parent = args.shift + + @xlabels = args.shift + @ylabels = args.shift + + if args[0].kind_of?(Hash) + @series_size = :stacked + else + @series_size = args.shift + end + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xlabels), array2tk_list(@ylabels), + @series_size) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(series, dat, col=None) + tk_call(@chart, 'plot', series, dat, col) + self + end + + def colours(*cols) + # set the colours to be used + tk_call(@chart, 'colours', *cols) + self + end + alias colour colours + alias colors colours + alias color colours + end + + ############################ + class HorizontalBarchart < Barchart + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createHorizontalBarchart'.freeze + ].freeze + end + + ############################ + class Boxplot < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createBoxplot'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] xaxis, ylabels [, keys]) + # xaxis := Array of [minimum, maximum, stepsize] + # yaxis := List of labels for the y-axis + if args[0].kind_of?(Array) + @xaxis = args.shift + @ylabels = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @xaxis = args.shift + @ylabels = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@xaxis), array2tk_list(@ylabels)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + + def plot(label, *values) + tk_call(@chart, 'plot', label, values.flatten) + self + end + end + + ############################ + class RightAxis < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createRightAxis'.freeze + ].freeze + + def initialize(*args) # args := ([parent,] yaxis [, keys]) + # yaxis := Array of [minimum, maximum, stepsize] + if args[0].kind_of?(Array) + @yaxis = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @yaxis = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + array2tk_list(@yaxis)) + end + private :_create_chart + + def __destroy_hook__ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{ + Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path) + } + end + end + + ############################ + class Timechart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createTimechart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] time_begin, time_end, items [, keys]) + # time_begin := String of time format (e.g. "1 january 2004") + # time_end := String of time format (e.g. "1 january 2004") + # items := Expected/maximum number of items + # ( This determines the vertical spacing. ) + if args[0].kind_of?(String) + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + super(*args) # create canvas widget + else + parent = args.shift + + @time_begin = args.shift + @time_end = args.shift + @items = args.shift + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call_without_enc(self.class::TkCommandNames[1], @path, + @time_begin, @time_end, @items) + end + private :_create_chart + + def period(txt, time_begin, time_end, col=None) + tk_call(@chart, 'period', txt, time_begin, time_end, col) + self + end + + def milestone(txt, time, col=None) + tk_call(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call(@chart, 'vertline', txt, time) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + self + end + end + + ############################ + class Ganttchart < Tk::Canvas + include ChartMethod + + TkCommandNames = [ + 'canvas'.freeze, + '::Plotchart::createGanttchart'.freeze + ].freeze + + def initialize(*args) + # args := ([parent,] time_begin, time_end, items [, text_width] [, keys]) + # time_begin := String of time format (e.g. "1 january 2004") + # time_end := String of time format (e.g. "1 january 2004") + # args := Expected/maximum number of items + # ( This determines the vertical spacing. ), + # Expected/maximum width of items, + # Option Hash ( { key=>value, ... } ) + if args[0].kind_of?(String) + @time_begin = args.shift + @time_end = args.shift + @args = args + + super(*args) # create canvas widget + else + parent = args.shift + + @time_begin = args.shift + @time_end = args.shift + @args = args + + if parent.kind_of?(Tk::Canvas) + @path = parent.path + else + super(parent, *args) # create canvas widget + end + end + + @chart = _create_chart + end + + def _create_chart + p self.class::TkCommandNames[1] if $DEBUG + tk_call(self.class::TkCommandNames[1], @path, + @time_begin, @time_end, *args) + end + private :_create_chart + + def task(txt, time_begin, time_end, completed=0.0) + list(tk_call(@chart, 'task', txt, time_begin, time_end, + completed)).collect!{|id| + TkcItem.id2obj(self, id) + } + end + + def milestone(txt, time, col=None) + tk_call(@chart, 'milestone', txt, time, col) + self + end + + def vertline(txt, time) + tk_call(@chart, 'vertline', txt, time) + self + end + + def connect(from_task, to_task) + from_task = array2tk_list(from_task) if from_task.kind_of?(Array) + to_task = array2tk_list(to_task) if to_task.kind_of?(Array) + + tk_call(@chart, 'connect', from_task, to_task) + self + end + + def summary(txt, tasks) + tasks = array2tk_list(tasks) if tasks.kind_of?(Array) + tk_call(@chart, 'summary', tasks) + self + end + + def color_of_part(keyword, newcolor) + tk_call(@chart, 'color', keyword, newcolor) + self + end + + def font_of_part(keyword, newfont) + tk_call(@chart, 'font', keyword, newfont) + self + end + + def hscroll=(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + scr + end + def hscroll(scr) + tk_call_without_enc(@chart, 'hscroll', scr) + self + end + + def vscroll=(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + scr + end + def vscroll(scr) + tk_call_without_enc(@chart, 'vscroll', scr) + self + end + end + + ############################ + class PlotSeries < TkObject + SeriesID_TBL = TkCore::INTERP.create_table + + (Series_ID = ['series'.freeze, TkUtil.untrust('00000')]).instance_eval{ + @mutex = Mutex.new + def mutex; @mutex; end + freeze + } + TkCore::INTERP.init_ip_env{ + SeriesID_TBL.mutex.synchronize{ SeriesID_TBL.clear } + } + + def self.id2obj(chart, id) + path = chart.path + SeriesID_TBL.mutex.synchronize{ + if SeriesID_TBL[path] + SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id + else + id + end + } + end + + def initialize(chart, keys=nil) + @parent = @chart_obj = chart + @ppath = @chart_obj.path + Series_ID.mutex.synchronize{ + @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_) + Series_ID[1].succ! + } + SeriesID_TBL.mutex.synchronize{ + SeriesID_TBL[@ppath] ||= {} + SeriesID_TBL[@ppath][@id] = self + } + dataconfig(keys) if keys.kind_of?(Hash) + end + + def plot(*args) + @chart_obj.plot(@series, *args) + end + + def dataconfig(key, value=None) + @chart_obj.dataconfig(@series, key, value) + end + end +end -- cgit v1.2.3