Red [
Title: "Google Charts API"
]
#macro ['use set locals block!] func [s e][
reduce [
make function! [
[locals [object!] body [block!]]
[do bind body locals]
]
make object! collect [
forall locals [keep to set-word! locals/1]
keep none
]
]
]
Rebol [
Title: "Google Chart API"
Version: 0.1.3
Author: "Christopher Ross-Gill"
Home: http://ross-gill.com/page/Google_Charts_and_REBOL
Date: 9-Aug-2008
Exports: [chart]
File: %google-charts.r
Purpose: {Generates a URL to access the Google Charts API}
]
chart: use [
root types ; settings
map uses envelop ; core functions
form-simple form-color form-list form-lists form-data ; type helpers
][
root: http://chart.apis.google.com/chart?
types: [
line "lc" line/xy "lxy" sparkline "ls"
bar "bvs" bar/horizontal "bhs"
pie "p3" pie/flat "p"
map "t" venn "v"
]
uses: func [proto [block!] spec [block!]][
proto: context proto
func [args [block! object!]] compose/only [
args: make (proto) args
do bind (spec) args
]
]
map: func [series [any-block!] action [any-function!] /deep][
also series: copy/deep series
while [not tail? series][
series: either all [deep block? series/1][
change/only series map/deep series/1 :action
][
change/part series action series/1 1
]
]
]
envelop: func [val [any-type!]][either any-block? val [val][reduce [val]]]
form-simple: use [to-61 codes][
codes: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
to-61: func [val [number! none!]][
if none? val [return "_"]
val: max min 1 val 0
pick codes 1 + round 61 * val
]
func [[catch] data [block!] separator [any-type!]][
rejoin map data :to-61
]
]
form-color: func [color [tuple!] /local out][
out: copy ""
repeat val length? color [
append out rejoin [back back tail form to-hex color/:val]
]
lowercase out
]
form-list: func [block [block!] separator [char! string!]][
remove rejoin map block func [val][
rejoin [
separator
switch/default type?/word val [
decimal! [round/to val 0.1]
tuple! [form-color val]
none! [-1]
][
switch/default val [
color ["bg"] chart ["c"] all ["a"]
solid ["s"] gradient ["lg"] stripes ["ls"]
][val]
]
]
]
]
form-lists: func [
block [block!] separator [char! string!] encode [function!]
/with subseparator [char! string!]
][
remove rejoin map block func [block][
rejoin [separator encode block subseparator]
]
]
form-data: func [data [block!] /local out val /text /flat /simple /label][
unless parse data: copy/deep data [some block!][
data: reduce [data]
]
case [
simple [rejoin ["s:" form-lists data "," :form-simple]]
flat [form-lists/with data "," :form-list ""]
label [form-list data/1 "|"]
text [rejoin ["t:" form-lists/with data "|" :form-list ","]]
true [form-lists/with data "|" :form-list ","]
]
]
uses [
verbose: false debug: func [val][either verbose [probe val][val]]
out*: ""
emit: func ['arg val][repend out* ["&" arg "=" form val]]
title: none
size: 320x240
type: 'line
simple: no
data: []
color: colors: labels: area: bars: scale: none
][
clear out*
if scale [
if zero? scale [scale: 1]
data: map/deep data func [value] compose [
value * (round/to divide pick [100.0 1.0] not simple scale 0.001)
]
]
emit cht any [select types type form type]
emit chs size
emit chd either simple [form-data/simple data][form-data/text data]
case/all [
title [emit chtt title]
any [color color: colors][emit chco form-data reduce envelop color]
labels [emit chl form-data/label envelop labels]
area [emit chf form-data area]
bars [emit chbh form-data bars]
]
rejoin [root debug next out*]
]
]