Seeking philosophical guidance on library interface design.
Alex Tweedly
alex at tweedly.net
Wed Apr 24 20:47:31 EDT 2019
Thanks everyone for great feedback and suggestions.
Below I've included the current summary specs; currently this is all
pretty much working, except for
titles (which I just haven't done yet :-), and a few minor tweaks to
handle improvements I've added to the spec from reading the "R" docs
(thanks for that pointer Richard).
I've pretty much decided to take Mark's and Bob's suggestion - but in
reverse :-) So the default will be to have default values for most
parameters, and implement some kind of "intelligent" guess for those
which need it (which it turns out is really only tick marks, grid lines
and labelling of each of those) - but supply a single parameter which
says "don't make guesses".
On 24/04/2019 14:54, prothero--- via use-livecode wrote:
> Also useful would be a message that sends the x,y data values as the mouse moves over it. That way it would be possible for me to build a little window that gives me data values and other information as needed. Perhaps it could be clicked on and off with a checkbox.
Yeah, I've been thinking about that - but haven't yet reached any kind
of solution. Need to think some more - in particular, should it try to
give messages when the mouse is over any line segment ? Or only when it
is over the data point at the ends of the line segments (and within the
bars of a bar-chart).
Anyway - here's the current spec, any further feedback welcome.
btw - my aim is to release a first (beta) version before the end of April.
A Graph has one or more sets of data plotted as an XY graph. There may
be multiple sets of data displayed in the Y axis - but all of those
share a single X-axis.
There are therefore a number of parameters which can be optionally
defined for the entire
graph; then there are other parameters which can be set for each of the
datasets to be displayed.
There are two distinct Y axes - the 'normal' one plus optionally one on
the right.
Each dataset will describe whether it uses the right axis, or defaults
to the normal one.
Global parameters
-----------------
?? XRange - specify min/max in X for drawing (i.e. USE THIS, ignore
values in datasets)
-- XRangeIncludes - list of x values to be included
-- XFit - round limits to multiple of this
?? YRange
-- YRangeIncludes, YFit - same for Y
?? YRightRange
-- YRightRangeIncludes, YRightFit - same for Y on right
-- Title - a title
-- XGridInterval - gap (in data units) between vertical grid lines (i.e.
for X valuea)
-- set to 0 (default) for no grid
?? XGridMinor - number of minor grids per major grid
?? set to 0 (default) for no minor grid
-- XTickInterval - same as XGridInterval, but for ticks.
-- 0 = no axis at all, empty = (default) axis but no tick
-- >0 = ticks at multiples of interval (0, 2, 4, ...)
-- <0 ticks at interval FROM xmin (maybe 1, 3, 5, ...)
--
-- XTickLabelSpacing : 'N' = put label at each N'th tick ...
-- YTickLabelSpacing : 'N' = put label at each N'th tick ...
-- backgroundcolor - color for background of the whole graph
-- YGridInterval, ??YGridMinor,?? YTickInterval - as X
-- YRGridInterval, ??YRGridMinor,?? YRTickInterval - as X for right side
?? XTGridInterval, XTGridMinor, XTTickInterval - as X for top side
-- DataIncludesX - if TRUE, then each line of each dataset contains an
X value
-- - otherwise, no X values are present in the datasets,
-- and this element contains (up to) two values :
initial and step X values
-- deault (i.e. empty) is for inital value of 0, and
step value 1
--
-- NB - applies to ALL datasets
-- 'itemDel', 'lineDel' : replacing comma/CR for convenience
-- Data - one or more datasets, numerically indexed, in bottom-to-top
drawing order.
Dataset Parameters
------------------
-- name - the name
-- graphtype one of bar, line, step, Xticklabels, Yticklabels,
Xgridlabels, Ygridlabels
-- for "line", it can be followed by additional optional
words :
-- - filled - fill in below this line, with fillcolor
-- - invisibe (i.e. no line segments, but still draw
markers)
-- for "step", it can be followed by additional optional
words :
-- - verticalFirst (default) or horizontalFirst
-- describe whether to go up/down then along, or
along then up/down
-- Note that bar, step and line graphs can be "stacked" - i.e. there
can be multiple Y values
-- producing "stacked" graphs.
-- color : colour value, one per line for stacked charts
-- lineSize : size (width) of the line to be drawn, one per line for
stacked charts
-- fillcolor : color for the filled in polygon, one per line for
stacked charts
-- fillblend : blend level for the filled polygon, one per line for
stacked charts
-- values - list of values for the dataset
-- - so either Y, or if DataIncludesX then X,Y
-- - or Y,Y,Y,Y... or if DataIncludesX then
X,Y,Y,Y,... - producing 'stacked' lines
-- NB these all share other values, but can have
different colors
-- - or, if graphtype=Xlabels then it is 'label' or if
DataIncludesX then X,Label
-- 'blend' - blend level for drawing
-- 'dropshadow' - put in a dropshadow
-- 'YRaxis' : use the Right axis for scaling, etc.
-- 'marker' : name of marker shape to use (diamond, square, ???)
-- 'markersize' : size of marker
-- 'markercolor' : color for marker
-- 'barDensity' : specifies the percentage of the ratio between bar
and gap
(e.g. 50 would say that each bar is the same size
as the gap,
75 would say the bar takes 3/4 of the unit width,
while the gap takes the rest, etc.)_
Default is 75
X Value spacing
For a graph consistng only of line charts, the calculation of X_value
spacing is straightforward. We calculate the spread of X data values
(i.e. min to max values, plus anything specified in an 'XIncludes', and
then rounded out to include anything needed for an 'XFit'). Let's call
this the "virtual data range". This range of values is then scaled to
cover the visual space from the Y-axis to the right-Y-axis.
However, for a bar-chart, we need to allow the space for a 1/2 gap width
plus a 1/2 bar width on each side of these (virtual) data values. Also,
we need to allow a way to specify the 'density' of the display - i.e.
how wide the bars are, and how wide the gaps between them are. And,
especially in the case of DataIncludesX
-- Xunit - X_unit (NB shared for all datasets in the whole graph)
X_unit specifies the unit size (i.e. in 'source data' terms)
The default is for the X_unit to be 1 (as it will be unless
DataIncludesX is TRUE), while the default for barDensity is 75.
Examples
--------
1. the simplest possible example.
put "1:2:4:8:16:15:14:13:12:22:17:15" into temp
replace ":" with CR in temp
put temp into sA["data"][1]["values"]
gmMakeGraph the long id of grp "mycanvas", sA
1a. same thing, using the itemDel feature.
put ";" into sA["lineDel"]
put "1:2:4:8:16:15:14:13:12:22:17:15" into temp
put temp into sA["data"][1]["values"]
gmMakeGraph the long id of grp "mycanvas", sA
2. A better example, using percentages.
put "0, 100" into sA["YRangeIncludes"] -- make sure we have full
percentage range shown
put 5 into sA[K]["YTickInterval"] -- tick every 5, label
it every 10
put 2 into sA[K]["YTickLabelSpacing"]
put "Better line chart" into sA["title"]
-- first data series
put "1:2:4:8:16:15:14:13:12:22:17:15" into tA[1]["values"]
replace ":" with CR in tA[1]["values"]
put tA into sA[K]["data"]
gmMakeGraph the long id of grp "mycanvas", sA
3. A bar + line chart, 2 data series, X values included
put "Simple bar & line chart" into sA["title"]
put TRUE into sA["DataIncludesX"]
put 0 into sA["YRangeIncludes"]
put 5 into sA["YTickInterval"]
put 2 into sA["YTickLabelSpacing"]
put 10 into sA["YGridInterval"]
-- first data series
put "1,13:3,11:4,14:7,17:8,22:9,29:12,45:13,3" into tA[1]["values"]
replace ":" with CR in tA[1]["values"]
put "bar" into tA[1]["graphtype"]
put "red" into tA[1]["color"]
-- second data series
put "1,4:3,12:5,7:9,5:10,23:11,7:12,33:13,9" into tA[2]["values"]
replace ":" with CR in tA[2]["values"]
put "diamond" into tA[2]["marker"]
put 7 into tA[2]["markersize"]
put "blue" into tA[2]["color"]
put "blue" into tA[2]["markercolor"]
-- third data series - not really data, but X-axis labels
put "Xticklabels" into tA[3]["graphtype"]
put "1,Jan:3,Mar:4,Apr:5,May:7,Jul:8,Aug:9,Sep:10,Oct:11,Nov:12,Dec"
into tA[3]["values"]
replace ":" with CR in tA[3]["values"]
put tA into sA["data"]
gmMakeGraph the long id of grp "mycanvas", sA
-- Alex.
More information about the use-livecode
mailing list