# IupGraph

Definition: | include pGUI.e Ihandle ih = IupGraph(integer drid, string attributes="", dword_seq args={})
Description: | Creates a resizeable graph with one or more datasets. drid: a routine_id that provides the dataset[s], see example and explanation below. For more information on the attributes and args parameters see IupSetAttributes(), and below. Returns: the identifier of the created element.
pwa/p2js: | Supported. In fact this control was expressly written (on desktop/Phix) to be automatically transpiled for p2js, and all attributes below have therefore been marked with + to indicate they are fully supported.
Notes: | An IupGraph is a Phix/pGUI invention, expressly written for pwa/p2js, but of course it can be freely used for strictly desktop-only purposes. It is a simplified alternative to IupPlot(), but written in pure Phix hll code and suitable for automatic transpilation to JavaScript, which should (also) make it much more amenable to user-supplied enhancements and improvements, although at the moment it is pretty much the simplest possible replacement/implementation. The main differences between IupGraph and IupPlot are: An IupGraph is pwa/p2js-compatible, whereas IupPlot is not. An IupGraph only contains a single plot, optionally with multiple datasets occupying the same screen area. Datasets are provided via a (single) function call, rather than auxillary functions, hence there is no explicit dataset management. The presence or absence of a legend box depends on "NAMES" being specified, rather than a LEGEND (YES/NO) attribute. Major tick/min/max values must be provided and are not automatically defaulted if absent. Logarithmic scales are not directly supported, see demo\rosetta\9billionnames.exw for a manual solution. There is no zoom/pan/crosshair/tip/selection or context menu. It is drawn using OpenGL, and as per IupPlot this means a slightly lower text quality, but at least it supports anti-aliasing. The MAP_CB, ACTION (ie redraw), and RESIZE_CB callbacks of the IupCanvas on which IupGraph is based are used/specified internally and are non-overridable. The routine specified by drid should provide data as follows:
        {{"BGCOLOR",CD_PARCHMENT},  -- (optional)
         {"Helvetica",CD_PLAIN,9},  -- (optional)
         {"XRID",format_as_date},   -- (optional)
         {"BARMODE","HORIZONTAL"},  -- (optional)
         {"NAMES",name{,name..}},   -- (optional)
         {px,py[,CD_BLUE[,mode]]}}  -- (multiple allowed)
If the background colour is not provided CD_WHITE is assumed (can also be set via the BGCOLOR attribute). If the font (for the axis values) is not overridden the values shown above will be used. While BGCOLOR/XRID/YRID/BARMODE can be supplied as above, or via attributes as detailed below, the display of a legend is controlled by the pre(/ab)sence of "NAMES" in the returned data object (there is no LEGEND attribute). Each dataset is a pair of sequences of x and y values such that length(px) is the same as length(py), and can optionally specify a colour (if not provided CD_BLACK is assumed), and when MODE=MARK a markstyle. Further refinements to this structure are expected, and hopefully will/can be added in a backwards-compatible way.
See Also: | IupCanvas
Example: |
    -- demo\rosetta\Plot_coordinate_pairs.exw
    include pGUI.e
    include IupGraph.e

    constant x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
             y = {2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0}

    function get_data(Ihandle /*graph*/) return {{x,y,CD_BLUE}} end function

    IupOpen()
    Ihandle graph = IupGraph(get_data,"RASTERSIZE=300x200"),
            dlg = IupDialog(graph,`TITLE="Plot coordinate pairs"`)
    IupSetAttributes(dlg,"MINSIZE=320x200") -- (nb not raster units/pixels)
    IupSetAttributes(graph,"XTICK=1,XMIN=0,XMAX=9")
    IupSetAttributes(graph,"YTICK=20,YMIN=0,YMAX=180")
    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
You can also set XTICK etc inside drid, which has been named get_data() here, and is the reason why it gets passed the graph handle. Note that IupPlot provides sensible defaults if none are provided, but I am not about to try reverse engineering or deciphering the two decades-worth of tweaks and fine tuning that probably/potentially involves. IupGraph() does not fare well at sizes below a certain threshold, beyond which ticks might overlap or even go negative, hence as shown the use of an explicit minimum size setting is recommended. Obviously all that sort of handling and more remains open to future improvement. See also demo\pGUI\graph1.exw demo\pGUI\graph2.exw demo\pGUI\graph4.exw demo\pGUI\IupSampleDialog.exw demo\rosetta\B-spline.exw, demo\rosetta\Convex_hull.exw, demo\rosetta\Plot_coordinate_pairs.exw, demo\rosetta\9billionnames.exw, demo\rosetta\Euler_method.exw, demo\rosetta\Goldbachs_comet.exw, demo\rosetta\Polynomial_regression.exw demo\rosetta\Modified_random_distribution.exw, needs updating, and IupGraph [***] demo\rosetta\Yellowstone_sequence.exw
Attributes: | Note that while an IupGraph is based on an IupCanvas, internally it uses the CanvasDraw primitives rather than the IupDraw ones, and hence the FONT attribute does not apply. In fact, at the time of writing, the only other attribute beyond RASTERSIZE I have yet made any use of is DRAWSIZE, that is beyond the IupGraph-specific attributes not inherited from IupCanvas as listed below.
BGCOLOR+ | Can be set on the graph, or provided via drid as above.
CD_CANVAS+ | Use `cdCanvas cd_canvas = IupGetAttributePtr(graph,"CD_CANVAS")` to retrieve the internal cdCanvas, if needed.
DRAWSIZE+ | Can be retrieved from inside the drid routine, should that help any.
DRID+ | While I don’t particularly recommend (aka haven’t tested) modifying it on-the-fly, it seems perfectly reasonable to retrieve and invoke the drid for secondary purposes, for instance to set a label or frame name accompanying each graph.
RASTERSIZE+ | Standard behaviour, except that IupGraph.e automatically sets it to NULL after the initial display to enable full resizing.
MODE+ | One of "BAR", "MARK", "MARKLINE", "LINE". Behaves as "LINE" if undefined or unrecognised, defaults to "BAR" if BARMODE is set.
BARMODE+ | Display as a bar chart. Can be "VERTICAL", "HORIZONTAL" or undefined. Default: "VERTICAL" if mode="BAR", else undefined. An error occurs if this is set to an unrecognised value, or MODE is neither "BAR" nor "" (which is then set to "BAR"). See demo\pGUI\graph4.exw for an example.
MARKSTYLE+ | Display as discrete marks, instead of lines or a bar chart (etc). Can be "HOLLOW_CIRCLE", "PLUS", "X" or undefined, and can be set on each dataset. Default: "X" if mode="MARK". Note that like setting BARMODE means you don’t have to set MODE, if you set a MARKSTYLE on the graph itself, MODE=MARK is automatically set, however the latter must be set to pick up a style off each dataset, so you (may) have to set both MODE=MARK and MARKSTYLE[per dataset] in order for things to work properly. Unrecognised settings are simple treated as "X", rather than triggering an error. See demo\rosetta\Goldbachs_comet.exw for an example.
GRID+ | Display the grid lines. Can be "YES"/"ON"/true or "NO"/"OFF"/false. Default: false.
GRIDCOLOR+ | grid colour. Default: CD_GREY (#C0C0C0). Should be set using (eg) IupSetInt(graph,"GRIDCOLOR",CD_LIGHT_GREY).
GTITLE+, XNAME+, YNAME+ | (optional) Text strings for the graph title and names for the x and y axis. Default: "". Aside: renamed from TITLE to GTITLE to avoid inheriting from the dialog or other container. See demo\rosetta\Yellowstone_sequence.exw for an example.
LEGENDBOX+ | Specify whether to draw a box around the legend, default: YES. As noted above the presence or absence of a legend explicitly depends on "NAMES" being specified.
LEGENDPOS+ | legend box position. Can be: "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT", "BOTTOMCENTER" or "XY". Default: "TOPRIGHT". For XY the position must be specified via the LEGENDPOSXY attribute.
LEGENDPOSXY+ | (untested) legend box position in the format "x,y" - specifically CD_EAST of the first text.
TITLESTYLE+ | (optional) A style suitable for passing to cdCanvasFont(). Should be set using (eg) IupSetInt(graph,"TITLESTYLE",CD_ITALIC). Applies to TITLE, XNAME, and YNAME. Default: CD_PLAIN.
XMIN+, XMAX+, YMIN+, YMAX+ | The range of x and y values. Fairly obviously XMIN should be <= min(px) for all datasets, and similar rules for the other three, otherwise parts of the graph may end up missing.
XMARGIN+, YMARGIN+ | Can be used to adjust the axis display when needed. Specified in pixels, default 10.
XYSHIFT+, YXSHIFT+ | Can be used to further adjust the axis display in a platform-specific manner when needed. Specified in pixels, default 0. See demo\pGUI\graph2.exw for an example, without XYSHIFT the dates on the x-axis were misplaced under pwa/p2js. (In an ideal world IupGraph.e would handle that sort of thing automatically, perhaps. There may yet be a need for XXSHIFT and YYSHIFT.)
XANGLE+, YANGLE+ | Specify an angle in degrees suitable for passing to cdCanvasSetTextOrientation(), default 0. A non-zero value rotates the tick labels, typically by +/-90. See demo\pGUI\graph2.exw for an example.
XCROSSORIGIN+, YCROSSORIGIN+ | Allow the axis to cross the origin and be placed inside the dataset area. Can be YES or NO (or true/false). Default: NO. See demo\pGUI\graph1.exw for an example.
XRID+, YRID+ | (optional) Specify a routine_id to use as a callback for formatting the tick labels. See demo\pGUI\graph2|4.exw for examples. Note the x and y elements must all be numbers, not, for instance, date() results, and these routines have to be able to decipher said numbers. In the case of graph2.exw, the x values are days since 1/1/1999, in the range 1..7000, though these routines actually get their (atom/integer) parameter from the (matching/equivalent) XMIN/XTICK etc. In the case of graph4.exw, the x values are 1..12, with xformat yielding "jan".."dec".
XTICK+, YTICK+ | The spacing between major ticks, as in "for x=XMIN to XMAX by XTICK do draw_tick(x) end for". (minor ticks have not yet been attempted)
XTICKFMT+, YTICKFMT+ | Specify a standard sprintf() format string for the tick labels. Default: "%g". Has no effect if XRID/YRID has been specified.
Callbacks: | You may not use or override ACTION or RESIZE_CB or MAP_CB. (You can use those on the dialog, just not on the graph itself.)