<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE document SYSTEM "../../rml2pdf/rml.dtd">
<document filename="diagra-userguide.pdf">
<!-- Last Modified:             $Date$ -->
<!-- Document Version Number:   $Revision$ -->

<!-- NB: THIS TEMPLATE ASSUMES THAT ANY IMAGES USED ARE AN 'images' -->
<!--    DIRECTORY WHICH IS IN THE SAME DIRECTORY AS THE RML FILE    -->

<template pageSize="(21cm, 29.7cm)"
        leftMargin="1.5cm"
        rightMargin="1.5cm"
        topMargin="1.5cm"
        bottomMargin="1.5cm"
        title="Diagra Documentation"
        author="ReportLab Europe Ltd"
        showBoundary = "0"
        allowSplitting = "20"
        >

    <pageTemplate id="cover">
    <pageGraphics>
        <lineMode width="1"/>
        <lines>
        72 132 523 132
        </lines>

        <image file="images/replogo.gif" x="155" y="600"/>

        <setFont name="Times-Roman" size="10"/>
        <drawString x="72" y="110">ReportLab Europe Ltd</drawString>
        <drawString x="72" y="98">Thornton House, Thornton Road</drawString>
        <drawString x="72" y="86">Wimbledon</drawString>
        <drawString x="72" y="74">London SW19 4NG, UK</drawString>

    </pageGraphics>
    <frame id="title" x1="88" y1="316" width="419" height="214"/>
    <frame id="noteNumberBox" x1="88" y1="288" width="419" height="28"/>
    <frame id="dateBox" x1="88" y1="260" width="419" height="28"/>
    </pageTemplate>

    <pageTemplate id="contents">
    <pageGraphics>
    </pageGraphics>
    <frame id="first" x1="72" y1="72" width="451" height="698"/>
    </pageTemplate>

    <pageTemplate id="inside_oneColumn">
    <pageGraphics>
        <lines>
        72 796 523 796
        </lines>
        <setFont name="Times-Roman" size="10"/>
        <drawString x="72" y="808">Diagra Documentation</drawString>
        <drawRightString x="523" y="808">$Revision$</drawRightString>
        <drawCentredString x="297.5" y="60">Page <pageNumber/></drawCentredString>
    </pageGraphics>
    <frame id="first" x1="72" y1="72" width="451" height="698"/>
    </pageTemplate>

    <pageTemplate id="inside_twoColumns">
    <pageGraphics>
        <lines>
        72 796 523 796
        </lines>
        <setFont name="Times-Roman" size="10"/>
        <drawString x="72" y="808">Diagra Documentation</drawString>
        <!--drawRightString x="523" y="808">
        %(docnumber)s
        drawRightString-->
        <drawCentredString x="297.5" y="60">Page <pageNumber/></drawCentredString>
    </pageGraphics>
        <frame id="columnOne" x1="1.5cm" y1="2.5cm" width="8.5cm" height="24.7cm"/>
        <frame id="columnTwo" x1="10.5cm" y1="2.5cm" width="8.5cm" height="24.7cm"/>
    </pageTemplate>

</template>


<stylesheet>
    <initialize>
            <!-- If these aren't required, set them to "", DON'T delete them or comment them out completely!-->

            <!--<name id="DocumentTitle" value=""/>-->
            <name id="DocumentTitle" value="Diagra Documentation"/>
            <name id="DocumentSubtitle" value=""/>
            <!--<name id="DocumentSubtitle" value=""/>-->
            <name id="DocumentNumber" value=""/>
            <!-- please keep date in format dd fullmonthname yyyy -->
            <name id="DateOfIssue" value="February 2010"/>
            <alias id="para.defaultStyle" value="body"/>
            <alias id="style.h1" value="h1"/>
            <alias id="h1.defaultStyle" value="h1"/>
            <alias id="style.h2" value="h2"/>
            <alias id="h2.defaultStyle" value="h2"/>

    </initialize>

    <paraStyle name="Title"
    fontName="Helvetica-Bold"
    fontSize="36"
    leading="44"
    textColor="darkblue"
    alignment="CENTER"
    />

    <!-- If the title is too long to fit in the box, use a two or three word title and then put -->
    <!-- the rest as a sub-title in the 'SubTitle' paraStyle -->
    <paraStyle name="SubTitle"
    fontName="Helvetica-Bold"
    fontSize="24"
    leading="29"
    textColor="darkblue"
    alignment="CENTER"
    />

    <paraStyle name="h1"
    fontName="Helvetica-Bold"
    fontSize="24"
    leading="28"
    spaceBefore="12"
    spaceAfter="2"
    alignment="LEFT"
    />

    <paraStyle name="h2"
    fontName="Helvetica-Bold"
    fontSize="10"
    spaceBefore = "8"
    spaceAfter = "3"
    alignment = "LEFT"
    />

    <paraStyle name="h3"
    fontName="Helvetica-Bold"
    fontSize="10"
    spaceBefore = "0"
    spaceAfter = "0"
    alignment = "LEFT"
    />

    <paraStyle name="body"
    fontName="Times-Roman"
    fontSize="10"
    leading = "12"
    alignment = "LEFT"
    firstLineIndent="0"
    spaceAfter="5"
    spaceBefore="5"
    />

    <paraStyle name="footer"
    fontName="Helvetica-Oblique"
    fontSize="8"
    alignment = "LEFT"
    spaceAfter="0"
    leading="9"
    />

    <paraStyle name="none"
    fontName="Times-Roman"
    fontSize="10"
    leading = "12"
    alignment = "LEFT"
    />

    <paraStyle name="nospace"
    parent="body"
    firstLineIndent="12"
    leftIndent="18"
    spaceAfter="0"
    />

    <paraStyle name="noindent"
    parent="body"
    firstLineIndent="0"
    spaceAfter="0"
    />

    <paraStyle name="bullet"
    parent="body"
    leftIndent="12"
    firstLineIndent="0"
    spaceAfter="0"
    bulletIndent="0"
    bulletFontSize="6"
    bulletFontName="ZapfDingbats"
    />

    <paraStyle name="nobullet"
    parent="body"
    firstLineIndent="0"
    leftIndent="12"
    bulletIndent="12"
    />

    <paraStyle
    name="indentedList"
    bulletIndent="6"
    leftIndent="24"
    spaceAfter="0"
    />

    <paraStyle name="mock_link"
    parent="nobullet"
    fontName="Courier"
    fontSize="10"
    textColor="blue"
    leading = "12"
    alignment = "LEFT"
    spaceBefore="0"
    spaceAfter="0"
    />

    <paraStyle name="code_snippet"
    parent="nobullet"
    fontName="Courier"
    fontSize="10"
    textColor="black"
    leading = "12"
    alignment = "LEFT"
    spaceBefore="12"
    spaceAfter="12"
    leftIndent="36"
    />

    <paraStyle name="code_snippet_noindent"
    parent="code_snippet"
    fontSize="8"
    leading = "11"
    leftIndent="0"
    spaceBefore="0"
    spaceAfter="12"
    />

    <paraStyle name="code_snippet_noindentnospace"
    parent="code_snippet_noindent"
    spaceAfter="0"
    />

    <blockTableStyle id="DatabaseTopStyle">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="12" start="(0,0)" stop="(-1,-1)"/>
    <blockLeading length="14" start="(0,0)" stop="(-1,-1)"/>
    <!--<lineStyle kind="LINEBELOW" colorName="gray" start="(0,0)" stop="(-1,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="gray" start="(0,0)" stop="(-1,-1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="gray" start="(0,0)" stop="(0,0)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="gray" start="(-1,-1)" stop="(-1,-1)" thickness="1"/>-->
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyle">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="12" start="(0,0)" stop="(-1,1)"/>
    <blockLeading length="12" start="(0,0)" stop="(0,1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,1)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseContinuationStyle">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,0)" stop="(-1,-2)"/>
    <blockLeading length="12" start="(0,0)" stop="(0,1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5" start="(0,0)" stop="(-1,-2)"/>
    <!-- invisible last row - so keep the same with as the first part -->
    <blockTextColor colorName="white" start="(0,-1)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="10" start="(0,-1)" stop="(-1,-1)"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyleEx2A">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="12" start="(0,0)" stop="(-1,1)"/>
    <blockLeading length="12" start="(0,0)" stop="(0,1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,1)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(1,-1)" stop="(1,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(1,1)" stop="(1,1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(1,1)" stop="(1,-1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(1,1)" stop="(1,-1)" thickness="1"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyleEx2B">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="12" start="(0,0)" stop="(-1,1)"/>
    <blockLeading length="12" start="(0,0)" stop="(0,1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,1)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(2,-1)" stop="(2,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(2,1)" stop="(2,1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(2,1)" stop="(2,-1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(2,1)" stop="(2,-1)" thickness="1"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyleEx2C">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockLeading length="12" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,0)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(0,0)" stop="(-1,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(0,0)" stop="(-1,-1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(0,0)" stop="(0,0)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(-1,-1)" stop="(-1,-1)" thickness="1"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyleEx2D">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica-Bold" size="10" leading="12" start="(0,0)" stop="(-1,1)"/>
    <blockLeading length="12" start="(0,0)" stop="(0,1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,1)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(2,-1)" stop="(2,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(2,1)" stop="(2,1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(2,1)" stop="(2,-1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(2,1)" stop="(2,-1)" thickness="1"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(3,-1)" stop="(3,-1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(3,1)" stop="(3,1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(3,1)" stop="(3,-1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(3,1)" stop="(3,-1)" thickness="1"/>
    </blockTableStyle>

    <blockTableStyle id="DatabaseStyleEx2E">
    <blockValign value="TOP" stop="(-1,-1)"/>
    <blockAlignment value="CENTER" start="(0,0)" stop="(-1,-1)"/>
    <blockLeading length="12" start="(0,0)" stop="(-1,-1)"/>
    <blockFont name="Helvetica" size="10" leading="10" start="(0,0)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(0,0)" stop="(-1,0)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(0,0)" stop="(-1,0)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(0,0)" stop="(0,-1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(-1,0)" stop="(-1,0)" thickness="1"/>
    <lineStyle kind="LINEBELOW" colorName="red" start="(0,1)" stop="(-1,1)" thickness="1"/>
    <lineStyle kind="LINEABOVE" colorName="red" start="(0,1)" stop="(-1,1)" thickness="1"/>
    <lineStyle kind="LINEBEFORE" colorName="red" start="(0,1)" stop="(0,1)" thickness="1"/>
    <lineStyle kind="LINEAFTER" colorName="red"  start="(-1,1)" stop="(-1,1)" thickness="1"/>
    </blockTableStyle>


    <blockTableStyle id="ExampleTableStyle">
    <blockValign value="TOP"/>
    <blockAlignment value="LEFT"/>
    <blockFont name="Times-Bold" size="8" leading="12" start="(0,0)" stop="(-1,0)"/>
    <blockFont name="Courier" size="8" start="(0,1)" stop="(-1,-1)"/>
    <blockLeftPadding length="-20" start="(0,1)" stop="(-1,-1)"/>
    <lineStyle kind="GRID" colorName="gray" thickness="0.5"/>
    </blockTableStyle>

</stylesheet>


<story>

<!-- PAGE 1 (COVER) -->

    <para style="Title">
<getName id="DocumentTitle"/>
    </para> <para style="SubTitle">
<getName id="DocumentSubtitle"/>
    </para>
    <nextFrame/>


    <para
    alignment="CENTRE"
    fontName="Times-Bold"
    fontSize="18"
    leading="28"
    textColor="black"
    >
    <getName id="DateOfIssue"/>
    <!-- Set these here so that they are available on later pages -->
    <name id="sectionNumber" value="1"/>
    <seqReset id="subsectionNumber"/>
    </para>



   <outlineAdd level="0"><getName id="DocumentTitle"/></outlineAdd>
   <setNextTemplate name="inside_oneColumn"/>

<nextFrame/>
<outlineAdd level="1">Contents</outlineAdd>

<para style="h2">
CONTENTS
</para>

<para style="nospace">
<name id="sectionNumber" value="1"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Overview
</b></para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
About This Document
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
What is Diagra?
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Other Documentation
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Limitations and Bugs
</para>

<spacer length="12"/>


<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="2"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Installation
</b></para>

<spacer length="12"/>

<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="3"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Using the Drawing Editor to Create Static Charts
</b></para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Introduction to the Drawing Editor
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Creating a New Project</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Adding Widgets</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting Widget Attributes</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Saving Your Project</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Exporting to Different Formats</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Opening Existing Files</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Adding Primitives - and another way to add widgets</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Miscellaneous Features</para>
<spacer length="12"/>


<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="4"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Working with Charts
</b></para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
BongoCorps's Drawing Classes</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Colours</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Fonts</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Collections</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Formats and Formatters: DecimalFormatter, NA_Label and Format Strings
</para>
<spacer length="12"/>


<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="5"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Creating Data Aware Charts
</b></para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Introduction to DataAwareDrawings: Plotmode, fileNamePattern and outDir</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting the Data Source</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting the Data Associations</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
A practical example: Slidebox.py</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Running the resulting scripts</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 2: Dotbox.py</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 3: Horizontalbarchart.py</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 4: Verticalbarchart.py</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 5: Linechart.py</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 6: SectorCylinderChart</para>

<spacer length="12"/>

<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="6"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
More about Using Axes</b>
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
ValueAxis
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
BongoYValueAxis
</para>

<spacer length="12"/>

<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="7"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
More on Data Sources</b>
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Making a Simple Chart Data Aware
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Changing the Data Associations on an Existing Chart
</para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Data Association Types: scalar, vector, matrix, tmatrix and rowmap
</para>

<spacer length="12"/>

<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="8"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
New Drawing Editor Features</b>
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Test Mode
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Errors
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Command Line Arguments
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Changing Environments
</para>
<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
The Diagnostics
</para>


<spacer length="12"/>

<condPageBreak height="36"/>
<para style="nospace">
<name id="sectionNumber" value="9"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Using 'Knockout'
</b></para>

<para style="nospace">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
'Knockout' - what it is, and why use it</para>


<nextFrame/>

<para style="h1">
<name id="sectionNumber" value="1"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
Overview</para>
<outlineAdd level="1">Overview</outlineAdd>

<outlineAdd level="2">About this document</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
About this document
</para>

<!--<para>This is normal, <b>this should be bold</b>, <i>this should be italic</i>,
<b><i>this should be bold-italic</i></b>, and back to normal again</para>-->
<para>
This document started out as specialised documentation for a large
customer's in-house systems which used Diagra and the Diagra Drawing
Editor. It is in the middle of being sanitised and made more generic
to become the Diagra documentation. This is a work in progress.
</para>
<para>
As such, it will be an overview of using the Drawing Editor with some
very specific examples. It will cover the Drawing Editor (guiedit) and some other software -
how to install it and how to use it to create charts.
It is <i>not</i> intended as a complete set of documentation for every
chart and every method for each chart. See the section on
'Other Documentation' (below) for info on how to get that.
</para>

<outlineAdd level="2">What is EPSCHARTS?</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
What is EPSCHARTS?
</para>
<para>EPSCHARTS was the original name for what has now evolved into
Diagra and the Diagra chart server. You may still see the name in some
code and in a few other places in this manual. This is a hangover from
previous versions - it is not a separate product.
</para>

<outlineAdd level="2">What is Diagra?</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
What is Diagra?
</para>
<para>Diagra is a process for batch-generating charts - originally in
Encapsulated Postscript but now in many other formats as well. This
has evolved through a number of iterations. </para>
<para>The current iteration is hopefully the right long-term workflow
and goes like this:</para>
<para style="bullet" bulletText="l">The <i>reportlab/graphics</i> package contains code to
let programmers generate standard chart types in several formats</para>
<para style="bullet" bulletText="l">ReportLab has also written some special chart types
for various customers with extra features</para>
<para style="bullet" bulletText="l">Programmers define some base "Drawing" classes including
these charts.</para>
<para style="bullet" bulletText="l">Designers use a GUI tool (the
Diagra Drawing Editor) to create several variants of these base classes.
These specify chart formatting attributes (size, color, label style
etc.) and also data-processing attributes (input data file name,
output directory, file format (not just EPS). They save these as
special python modules.  </para>
<para style="bullet" bulletText="l">When you run one of these modules
(e.g. with a double-click), it looks for a data source (CSV file or
ODBC database), reads it, and generates a batch of charts. These will
look like the prototype, except that the data for each chart is of
course different.</para>

<outlineAdd level="2">Other Documentation</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Other Documentation
</para>
<para>
<b>xxxxxxxx.epscharts.pdf and updatedoc.py</b>
</para>
<para>
The most up-to-date and complete documentation on the various charts
on your system will be the documentation that is autogenerated.
</para>
<para>
There is a program called updatedoc.py (which should be in your
xxxxxxxx/epscharts directory). When you run this, it will run over
your epscharts directory and create a document called
'xxxxxxxx.epscharts.pdf' in your documentation directory.
</para>
<para>
This document contains all the classes (i.e. charts) that are available
to you on your machine, along with a brief description of what it
does, the attributes you can set for it ('Public Attributes') and an
example of what one looks like.
</para>

<para>
<b>Other documents</b>
</para>
<para>
Both the core ReportLab toolkit and the ReportLab graphics package
come with their own documentation. That for the core toolkit is called
'userguide.pdf', and that for graphics is called 'graphguide.pdf'.
Both these files should be in the reportlab\docs directory under your Python
directory.
</para>


<outlineAdd level="2">Limitations and Bugs</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Limitations and Bugs
</para>
<para>
At the time of writing we hope we now have an overall process which
makes sense.  However, each chart has dozens of different attributes
which need debugging.  We therefore expect a period of rapid
change while this stabilizes and before all of the attributes work.
</para>

<para>
Unfortunately, some of these changes (especially if we completely
delete some attribute) will means 'starting again'
with existing drawing files.
</para>

<para>
Occasionally, the drawing editor may get your settings confused (e.g.
forcing you to have a full screen for your editor screen). If
this is the case, find the file called <b><i>_guiedit.ini</i></b>
(which should be in the same folder as the drawing editor program
itself - guiedit.py ). Delete it. This will be regenerated the next
time you start up the Drawing Editor, and should clear your problem.
</para>


<setNextTemplate name="inside_oneColumn"/>
<nextFrame/>

<outlineAdd level="1">Installation</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="2"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
Installation
</para>

<para>
Please follow http://www.reportlab.com/software/installation/ for the most up-to-date
instructions on installing our libraries along with their dependencies.
</para>

<para style="bullet" bulletText="l">
<b>Optional step (for Windows only): Creating a shortcut to the Drawing Editor</b>
</para>

<para style="nobullet">
If you will be using the Drawing Editor on a regular basis, you should put a
shortcut to it on your desktop to make life easier. To do this, right click on
your desktop and 'New' then 'Shortcut'. Then copy this line
c:\Python26\pythonw.exe c:\python26\Lib\site-packages\rlextra\graphics\guiedit\guiedit.py
and paste it into the location text box that appears in the dialogue, and save.
</para>

<para style="nobullet">
Double clicking on this icon will now have the same effect as
double-clicking on the original: it will start up the Drawing Editor, but without
having to navigate to it in Windows Explorer. And the change to the target in the
Properties box means that it doesn't open an extra shell window when it runs.
</para>

<nextFrame/>

<outlineAdd level="1">Using the Drawing Editor to Create Static Charts</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="3"/><seqReset id="subsectionNumber"/>
<b><getName id="sectionNumber"/>
Using the Drawing Editor to Create Static Charts
</b></para>

<outlineAdd level="2">Introduction to the Drawing Editor</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Introduction to the Diagra Drawing Editor
</para>

<para>
The Diagra Drawing Editor (guiedit.py) is the graphical editor for EPS charts.
If you look in your 'rlextra' directory (under Python22), you should
find a 'graphics' directory which should in turn have a 'guiedit'
subdirectory. Inside that is the GUI Editor program - 'guiedit.py'.
Double-clicking on that should give you something like this:
</para>

<spacer length="6"/>
<!--full size:-->
<!--illustration width="409" height="528"-->
<!--at 60%:-->
<illustration width="245" height="316" align="CENTER">
<image file="images/gui_pic1.gif" x="0" y="0" width="245" height="316"/>
</illustration>
<spacer length="12"/>

<para>
From the top, the elements of this display are:
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
<i>Title bar</i>
</para>
<para style="nobullet" spaceBefore="0">
Just like any other program, this is where the name of the program is
displayed, and which contains the Minimize, Maximize and Close
buttons.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
<i>Menu bar</i>
</para>
<para style="nobullet" spaceBefore="0">
This is the area which contains drop-down menus - click on 'File',
'Options', 'Actions', 'Windows' or 'Help' to see the associated menu.
Also, notice how if you leave the cursor over one of the menu titles,
a floating box  appears with some text telling you what it is (you
might know these as 'tooltips' if you are a Windows user, or 'balloon
help' if you are a Mac user). Most buttons and fields in the Drawing
Editor have these. If you find them annoying, you can turn them off by
using the 'Tooltips off'/'Tooltips on' item in the Options menu.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
<i>Main Window</i>
</para>
<para style="nobullet" spaceBefore="0">
The large black area which currently has the words 'ReportLab GUI
Drawing Editor' in it is the 'Main Window'. This is the area which will
contain the graphical displays of your charts.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
<i>Log Window</i>
</para>
<para style="nobullet" spaceBefore="0">
The Drawing Editor keeps a log of its actions. These are displayed in
their own window (the Log Window). This window can be turned off if
you don't find them useful or to make more room on screen. You can do
this by going to the 'Windows' menu and selecting 'src window on',
which will then toggle to off (and change colour from green to red).
</para>

<para>
Some other points to notice before we move on to doing something
useful using the Drawing Editor. The frame the contains all these other windows
is resizable. If you move the cursor to the left or right hand edges
of the Drawing Editor window, it will change into an horizontal arrow with
arrowheads at either end. When the cursor looks like this, you can
click-and-drag to move the edges out horizontally. Similarly, when you
place the cursor over the top or bottom edges of the window, it
changes to a vertical arrow with arrowheads at the top and bottom.
This means that you can click-and-drag to move the edges vertically.
And when you place it over the bottom left hand corner, it changes to
a diagonal arrow - you can then move it horizontally and vertically at
the same time to resize it in both directions.
</para>
<para>
There is a thin line over the divider between the main window and the
log window (just over where it says 'Log'). If you move the cursor
over it, you see it changes to the vertical arrowheads. You can click
and drag to shrink or grow this window vertically. If you look at the
line, it has a small square box or button almost at the right hand
edge. If you notice a box like this on any other divider in the Drawing Editor,
then you can click-and-drag it to resize the windows it borders.
</para>

<para>
From the Options menu, select the item 'Searched Packages'. You should
get a dialogue that looks like this:
</para>
<spacer length="6"/>
<!--full size:-->
<!--illustration width="159" height="314"-->
<!--at 60%:-->
<illustration width="95" height="188" align="CENTER">
<image file="images/gui_pic3.gif" x="0" y="0" width="95" height="188"/>
</illustration>
<spacer length="12"/>

<para>
This lists the packages that the Drawing Editor searches to find charts. You may
have to add a package (i.e. a directory which contains the reusable
Python code to create the charts, as well as a file called __init__.py)
if you cannot find the charts that you need (but you know they exist
on your hard disk). 'Package Exclusions' from the same menu provides you
with a similar dialogue which does the same thing for the excluded
packages - those that are deliberately ignored when the packages are
being imported.
</para>

<para>
As well as the immediate function of this pop-up, it's worth noting
the two small coloured arrows at the left and right. Whenever you see
arrows like this in a dialogue in the Drawing Editor, you will know that they
have to do with navigation. In this case they point up and down - if
you have clicked to highlight a package, these up and down arrows move
you up and down the list. As we will see later, they can also be used for
navigating the attributes in a list as well as just moving up and
down the list itself.</para>

<outlineAdd level="2">Creating a New Project</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Creating Static Charts: Creating a New Project</para>

<para>
The 'New' item from the File menu allows you to create a new Project.
This will pop-up a dialogue which prompts you for the name of the
project, and allows you to chose the name of the class from which it
will be inheriting.
</para>

<spacer length="6"/>
<!--full size:-->
<!--illustration width="537" height="528"-->
<!--at 60%:-->
<illustration width="272" height="316" align="CENTER">
<image file="images/gui_pic2.gif" x="0" y="0" width="272" height="316"/>
</illustration>
<spacer length="12"/>

<para>
As you can see from this illustration, we'll be using the
class called 'Drawing' as the basis for our new static chart. The
illustration below shows you what we get when we click on the
OK button to open it up. This doesn't look very exciting, since the
Drawing class just gives us a blank canvas to work on. All of our static
drawings will inherit (directly or indirectly) from this class. You should
also notice some more windows appearing - more on those in a few
paragraphs.
</para>

<spacer length="6"/>
<!--full size:-->
<!--illustration width="410" height="528"-->
<!--at 60%:-->
<illustration width="245" height="316" align="CENTER">
<image file="images/gui_pic3a.gif" x="0" y="0" width="245" height="316"/>
</illustration>
<spacer length="12"/>

<outlineAdd level="2">Adding Widgets</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Adding Widgets
</para>

<para>
We can add contents to this drawing. In the 'Actions' menu there is a
menu item called 'Add Widget'. A widget is a reusable shape that can
be 'drawn'. Widgets can be as simple or as complex as you want. You
can create your own widgets, but in most cases you will be modifying
existing, pre-created widgets.
</para>

<para>
If you go 'Actions' and select 'Add Widget', you should
get a dialog appearing that looks similar to the one below. For the
purposes of this example, scroll down it until you see 'Pie' and click
on it. You should see 'Pie' appear in the box labelled 'Widgets?'.
Then give it a name - enter 'NewPie' in the box labelled 'New Widget Name'.
</para>

<spacer length="6"/>
<!-- at 100% -->
<!--<illustration width="252" height="343">-->
<!--<image file="images/gui_pic3b.gif" x="0" y="0" width="252" height="343"/>-->
<!-- at 60% -->
<illustration width="120" height="180" align="CENTER">
<image file="images/gui_pic3b.gif" x="0" y="0" width="120" height="180"/>
</illustration>
<spacer length="12"/>

<para>
As you can see (below), as well as the main and log windows we already
had when we started the Drawing Editor, we now have three new windows: the
'Attributes' window (labelled 'self Attrs'), the entry field and the
'Source' window. If you can't see any of these windows, click on the
dividers to resize things until you do (e.g., you may have to grab and
drag the bottom edge to see the Log window).
</para>

<spacer length="6"/>
<illustration width="240" height="360" align="CENTER">
<image file="images/gui_pic5.gif" x="0" y="0" width="240" height="360"/>
</illustration>
<spacer length="12"/>

<para>
The <i>attributes window</i> shows a list of attributes that this class has.
The 'self' in 'self Attrs' refers to the fact that these attributes
are for the base class (rather than for one of its attributes). Some
of these attributes themselves have attributes that you can change.
For example, double click on the line that says 'NewPie =
Pie(Widget)'. The 'self Attrs' changes to 'self.pieChart Attrs' to
show that you are now changing the attributes for the pie chart rather
than for the class as a whole, and the list of attributes displayed
changes to those for the pie chart (NewPie).
</para>

<para>
If you have finished with the attributes for NewPie, you can
go back to the attributes for the whole chart by clicking on the red
up-arrow on the right hand side of the entry field. The blue
down-arrow on the left takes you down a level ('drilling down')
if that attribute has attributes that you can change.
Double-clicking on a class with attributes does the same as the
blue arrow, but double clicking on the red text with the class name
('self Attrs') does the same as the red up-arrow (i.e. takes you up a level).
</para>

<para>
The <i>entry field</i> shows the attribute you have currently selected from
the Attribute window. You can make changes in this one-line
window, and these will be reflected in the Attributes window as soon
as you hit enter. These changes also show up in a more graphical way
in the main window, so you can see exactly what those changes do to the
look of a chart.
</para>

<para>
The <i>source window</i> shows the Python source code. This may be
especially useful to you if you are a programmer, but is also very
useful if you're not. Looking in the source window, you should see a
line that looks like this:</para>
<codesnippet language="python">
self._add(self,Pie(),name='NewPie',validate=None,desc=None)
</codesnippet>
<para>
This is the line the actually adds the widget for the Pie chart. If
you right click on it, you should see another dialog pop up:
</para>

<spacer length="6"/>
<!--at 60%:-->
<illustration width="240" height="60" align="CENTER">
<image file="images/gui_pic6.gif" x="0" y="0" width="240" height="60"/>
</illustration>
<spacer length="12"/>

<para>
This alter edit dialog is very handy. It allows you to alter the text
(to do things such as changing the name of a widget - if you decided
to call it PieChart rather than NewPie), and to totally remove an
object that you have added by mistake. If you do want to close the
source window, go to the Windows menu and select 'Src window on' -
this will toggle it to off. You can always toggle it back on later.
</para>


<outlineAdd level="2">Setting Widget Attributes</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting Widget Attributes
</para>
<para>
By default, the width and height for this pie are 100x100. This is
pretty small - but you can change this. If you have clicked on the
line that said 'NewPie = Pie(Widget)' in the attributes window, you
should see a scrollable list of all the attributes for the pie appear
in the Attributes window. Click on the line that says 'height = 100' -
this should now appear in the entry field below it. You can click in
this and edit it. Change the 100 into 200. Do the same for the width
attribute. The chart in the main window should now be bigger. You can
also change the x and y attributes - these are the x and y
co-ordinates for the bottom left hand corner of the widget. Change the
x to 25, and the y to 10 - you'll see why later.
</para>

<para>
It is still just a circle
though - it has no data to display. Most of our charts (except for a
couple of extremely simple ones) have an attribute called 'data'. Our
NewPie is no exception. The data attribute is a list, and currently it
just contains the number 1. You can change this by clicking on the
line that says 'data' in the attributes window, and then editing it in
the text entry box. The data must be a list (i.e., be contained in
square brackets), and it must be separated by commas. It doesn't
matter if you use whitespace between the elements or not. So, </para>
<codesnippet language="python">[23]
[1, 2, 3]
[2,3,4]
</codesnippet>
<para>
are all valid lists for the data attribute, but these are not:
</para>
<codesnippet language="python">
(1,2,3)
1,2,3
'1,2,3'
</codesnippet>
<para>
Most widgets will have attribute checking switched on. This means that
they check if what you are entering is a valid data type for that
attribute. If you try and enter an invalid list for data - or if you
try and enter something that isn't suitable for any other attribute,
say a string instead of a number - you will get a 'traceback'. The one
for this attribute would look something like this:
</para>
<codesnippet language="python">
<![CDATA[
Traceback (most recent call last):
  File "\rlextra\graphics\guiedit\guiedit.py", line 920, in attrChange
    self.redraw(action='redraw')
  File "\rlextra\graphics\guiedit\guiedit.py", line 718, in redraw
    self.newDrawing()
  File "\rlextra\graphics\guiedit\guiedit.py", line 826, in newDrawing
    self.project.getSample()
  File "\rlextra\graphics\guiedit\guiedit.py", line 392, in getSample
    exec "%s\n_x=%s()\n" % (self.buildText(),self.className) in locals()
  File "<string>", line 14, in ?
  File "<string>", line 13, in __init__
  File "reportlab\graphics\widgetbase.py", line 49, in __setattr__
  File "reportlab\lib\attrmap.py", line 72, in validateSetattr
AttributeError: Illegal assignment of '23' to 'data' in class Pie
]]>
</codesnippet>
<para>
The last line is the most important - that's the one telling you what
has gone wrong. In this case, you'd have entered '23' instead of
'[23]'
</para>

<para>
Width, height, x, y and data are common attributes for most of the widgets you will be working with.
</para>

<outlineAdd level="3">Simplifying Attributes</outlineAdd>
<para style="h3">Simplifying Attributes</para>

<para>
When you change attribute properties you will see lines being added to the source code in the source window. When you are assigning a new value to an attribute that you have already modified, the new attribute assignment is simply appended to the code, with the last assignment being the one that is effected. An example of this in the screen shot below showing multiple attempts to set the chart.height.
</para>

<spacer length="6"/>
<!--at 60%:-->
<illustration width="252" height="123" align="CENTER">
<image file="images/gui_pic_pre_simplify.gif" x="0" y="0" width="252" height="123"/>
</illustration>
<spacer length="12"/>

<para> 
    A list of the attributes, might be handy for viewing a history of what has been changed. However after a period of time seeing particular attributes assigned multiple times might seem confusing. If you want to remove the duplicate settings you have two options, either manually by selecting the 'File' menu then selecting 'Simplify properties' or automatically when you save your chart by selecting 'Save on Simplify' in the 'Options' menu (saving you chart is covered the subsequent section). 
</para>

<blockTable>
    <tr>
        <td vAlign="TOP">
            <para>Manualy Selecting 'Simplify properties'</para>
            <illustration width="140" height="181" align="CENTER">
            <image file="images/gui_pic_menu1_simplify.gif" x="0" y="0" width="140" height="181"/>
            </illustration>
        </td>    
        <td vAlign="TOP">
            <para>Setting 'Save on Simplify'</para>
            <illustration width="150" height="211" align="CENTER">
            <image file="images/gui_pic_menu2_simplify.gif" x="0" y="0" width="150" height="211"/>
            </illustration>
        </td>    
    </tr>
</blockTable>

<para>
After you have run 'Simplify Properties', or have 'Save on Simplify' set to 'on',  if you look at the 'log' window you should see that the duplicates have been removed.
</para>

<spacer length="6"/>
<!--at 60%:-->
<illustration width="251" height="187" align="CENTER">
<image file="images/gui_pic_post_simplify.gif" x="0" y="0" width="251" height="187"/>
</illustration>
<spacer length="12"/>

<outlineAdd level="2">Saving Your Project</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Saving Your Project</para>

<para>
If you have made all the changes described above, you should have
something that looks like this:
</para>



<spacer length="6"/>
<!--at 60%:-->
<illustration width="244" height="384" align="CENTER">
<image file="images/gui_pic4.gif" x="0" y="0" width="244" height="384"/>
</illustration>
<spacer length="12"/>


<para>
We've now made enough changes to be obvious that the chart has
changed. Now we can save it. From the File menu, select the option
'Save'. This gives you a save dialog which allows you to navigate the
file system. You don't have to save the file on your local machine -
you can save it on any mapped drive or server that is available to you.
Enter the filename of 'NewPieChart' and click on 'OK' to save this
chart. The Drawing Editor will automatically append a .py suffix onto the
filename (to show it is a Python file).
</para>


<spacer length="6"/>
 <!--full size:-->
 <illustration width="337" height="212" align="CENTER">
 <image file="images/gui_pic7.gif" x="0" y="0" width="337" height="212"/>
 </illustration>
 <spacer length="12"/>

<para>
When the main window is visible again, notice how the file line above the main window now contains the file name.
</para>
<para>
Now we have finished with the immediate changes and saved the chart, we can close it.
Select 'Close' from the file menu. The main window goes back to black
with the 'ReportLab GUI Drawing Editor' line to show that we have no
chart loaded.
</para>

<spacer length="6"/>
<!--full size:-->
<!--illustration width="306" height="149"-->
<!--full size:-->
<illustration width="183" height="89" align="CENTER">
<image file="images/gui_pic8.gif" x="0" y="0" width="183" height="89"/>
</illustration>
<spacer length="12"/>

<para>
If you have forgotten to save the changes you have made to the chart,
you will see a dialog box like the one above. Click on 'No' to keep this
chart open and go back and save the chart, or click on 'Yes' to close it
and lose any changes you have made.
</para>

<outlineAdd level="2">Exporting to Different Formats</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Exporting to Different Formats</para>

<para>
The Drawing Editor also allows you to save your file in a bitmapped graphic
format. To do this, go to the 'File' menu and select 'Export'. A 'Save
As' dialogue box will appear, but it has the addition of a
'save as type' dropdown box. You can select from the available formats
(including Jpeg or GIF suitable for web use, Postscript or
Encapsulated Postscript, TIFF and PNG).
</para>
<para>
It's not advisable to export a file without saving it using the 'save'
or 'save as' options. Once a file has been exported, it is impossible
to convert it back again. Exporting a file is a strictly one way process.
</para>

<outlineAdd level="2">Opening Existing Files</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
<b>Opening Existing Files</b></para>
<para>
Once you have created a chart, you shouldn't have to use the 'New'
menu item again. That should be a once-per-project step.
</para>
<para>
Back in the Drawing Editor, you can select 'Open' from the file menu to open an
existing chart. For this example, open the file NewPieChart.py. Let's
make another couple of changes:
</para>
<para>
Double click on the 'NewPie = Pie(Widget)' to take you back into the
attributes for the PieChart. Click on the line 'labels = None',
which should appear in the entry field ready to be
changed. None in this context is a
Python object that means 'null', and should be used where you don't want
an attribute to be used (rather than trying to use empty strings,
empty lists etc which may cause unexpected behaviour). You can change
it to something like 'labels = ['a', 'b', 'c']' to make labels appear.
The labels attribute accepts a list in the same way data does. (You
should also see why we suggested making the x for the pie 25 - if it
wasn't this big, you wouldn't have been able to see the label).
</para>

<para>
If you select 'Save' from the file menu, the chart will be saved to
the file that it came from. Since the Drawing Editor already knows the file name,
you will not be asked to give one, and no save dialogue will appear. If you
want to save this to a different file name, use the 'Save as' item from the
file menu instead.
</para>

<outlineAdd level="2">Adding Primitives (another way to add widgets)</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Adding Primitives - and another way to add widgets
</para>

<para>
As well as adding widgets from the menu, you can also add them from
the text entry box (ie, the "entry box" with the white background).
So to add the pie chart, we could have typed
</para>
<codesnippet language="python">
add(Pie(), 'NewPie')
</codesnippet>

<para>
You may have to highlight and remove what is already there to do this
- in this case highlight "background = None", hit delete, and type in the line above.
</para>

<para>
The 'Pie' is the name of the widget, and the 'NewPie' is the name that
we will be referring to it by. Pie must be followed by those brackets.
If you know the structure of the Pie widget, you can use those
brackets to pass in attributes for it to use, but in most cases it is
easier to leave them empty and set them using the Drawing Editor.
</para>

<para>
The Drawing Editor doesn't just allow you to add widgets in this way. You can
also add graphics primitives.
If you type
</para>
<codesnippet language="python">
add(Rect(0,0,20,20), 'Rectangle')
</codesnippet>
<para>
you will see a rectangle appear in the bottom left hand corner. The
numbers in the brackets represent the following attributes: x, y, width, height.
You can also do this for other graphics primitives (such as Circle and
Ellipse). Notice that because these are primitives rather than
widgets, you have to give them certain required parameters, rather
than just let them use their own defaults and edit them later.
For more information about what these are and how to use them, look in
the Graphics Guide documentation (or read the code and docstrings in
reportlab\graphics\shapes.py).</para>

<para>Some examples:</para>
<codesnippet language="python">
add(Circle(20,20,20), 'MyCircle')
add(Ellipse(20,20,20,20), 'MyEllipse')
add(Line(0,0,20,20), 'MyLine')
</codesnippet>

<para>
As well as the more obvious graphics primitives, you can also add
lines of text to a chart. As an example, type this into the text entry box:
</para>
<codesnippet language="python">
add(String(125,250, 'Example Bar Chart'), 'Title')
</codesnippet>

<para>
Looking at the chart, nothing seems to have changed. This is because,
while the string has been added it's been added in a place off the top
of the chart. To make it visible, edit the height and width
attributes (of the chart, not the pie). Make them something sensible
like a width of 250 and a height of 275 (to allow for the title). The
other alternative is of course to move the string to a different place
on the chart - but the important thing to notice is that there isn't
any sanity checking of where you put it.
</para>

<para>
When we added the string, we gave it a y attribute of 125, which is in the centre of the chart. To
make sure the string actually is centred, you need to edit its
attributes. Click on the line in the attributes window which says
'Title = String(Shape)'. Right-click on the textAnchor line, and you
can see the options to select from. 'Start' makes the x position the
start of the line of text, 'end' makes the end of the line appear at the
x position, and 'middle' centres it. You can also change the font to be
used for the string, its size and various other attributes from here.
</para>

<para>By this point, you should have enough knowledge to put together
a static chart at least as complex as the one below:</para>

<spacer length="6"/>
<illustration width="152" height="166" align="CENTER">
<image file="images/gui_pic9.gif" x="0" y="0" width="152" height="166"/>
</illustration>
<spacer length="12"/>


<nextFrame/>
<para><b>Miscellaneous Features</b></para>
<para>
A few quick notes about Drawing Editor features that we haven't mentioned yet:
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
Zoom set</para>
<para style="nobullet">
This item (from the Windows menu) allows you to zoom in or out of the
chart. In other words, it magnifies or decreases the size of the image
in the main window.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
Clear log window</para>
<para style="nobullet">
This item (from the Windows menu) removes all the text from the log
window. Useful if you have large amounts that you no longer want to
scroll through.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
Reload module</para>
<para style="nobullet">
This item (from the Actions menu) make the Drawing Editor reload a module. Useful
if you have edited or updated the Python file for one a class or
drawing while you have the Drawing Editor still open. Instead of shutting it down
and restarting to make sure the Drawing Editor notices the change, you can use
'reload module' and select the module to reload and update.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
Debug</para>
<para style="nobullet">
This item (from the Option menu) turns on some debugging information
printouts. These are normally only of use to developers.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">
Exit</para>
<para style="nobullet">
This item, in the File menu, quits out of the Drawing Editor program.</para>


<nextFrame/>
<outlineAdd level="1">Working with Charts</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="4"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
Working with Charts
</para>
<para>
This chapter covers some general details of the chart classes and their
attributes.
</para>

<condPageBreak height="84"/>
<outlineAdd level="2">Working with Collections</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Collections
</para>
<!--
<para>
<i>to do.</i>Explain what they are, and about customizing the whole thing
or just one.  How to pick out an item (e.g. type
[3].popout = 5 when [3] was not even in the list)
</para>
-->

<para>
A number of attributes for charts are 'Collections'. A collection in
this instance is a 'smart collection class' under the hood which
allows you to change attributes for just one or for all of the items
in a set. These sets can be the slices in a pie chart, or the labels
or barLabels in a line chart. They even allow you to change the
attributes for an item which doesn't exist yet!
</para>

<para>
If you have a source distribution, open the file named
'example_collections_1.py' from the 'samples' directory.  Click down
into the attributes for the pie chart. You should see a line like
this:
</para>

<codesnippet language="python">
slices              = TypedPropertyCollection(WedgeProperties(PropHolder))
</codesnippet>

<para>
This line represents a collection. Double click on the line to show the
attributes of the collection:
</para>

<codesnippet language="python">
[0].fillColor   = darkcyan
[1].fillColor   = blueviolet
[2].fillColor   = blue
[3].fillColor   = cyan
[8].fillColor   = green
fillColor   = pink
</codesnippet>

<para>
These attributes fall into two different categories.
</para>

<para>
If a line in a collection (such as the 'slices' collection above)
starts with a number in square brackets, that line refers only to that
numbered element in the collection. So '[2].fillColor = blue' sets the
filling only for the third wedge in the chart (since we start counting
from 0). Any attribute that appears in a collection can have a numeric
index added as a prefix to define that attribute for one element of
the collection.  In our pie example, you could set
<i>strokeWidth</i>, <i>strokeDashArray</i>,
<i>strokeColor</i>, <i>popout</i>, <i>labelRadius</i> or <i>fillColor</i> for any individual slice
just by adding a prefix like '[0].' to the start of the line.

</para>

<para>

In contrast, if a line in a collection begins with an ordinary
attribute name, then that line sets the default value for all of the
analogously-named numbered attributes in the collection. For example,
the last line above makes all the wedges in your pie chart pink by
default.

</para>

<para>
You should be careful when mixing the two kinds of statements. One of
the second type (with no numeric index) sets the attributes for all
the elements in the collection - but only if none of the second type
are used. The kind with the numeric index always over-ride the more
general kind of statement. These general, un-numbered statements then
become a default which is used as a fallback when no specific
statement applies to a particular element. (e.g. if you define a
default fillColor with one of these un-numbered statements, then
define the fillColor for elements [0], [2] and [4], the default
fillColor statement would apply to elements [1] and [3]).
</para>

<para>
If our chart has fewer than 9 slices, then you might expect the
second-to-last line in the pie chart example above to cause a
problem. It doesn't. You should think of these statements as
prescriptions for what to do to a member of the collection if it
exists - if it doesn't this prescription is silently ignored. This
also means that when you are using the Drawing Editor to edit a chart,
you can edit the attributes for an element which isn't even in the
list which appears in the attributes window.
</para>

<para>
Another thing to be aware of with collections is the way that they
'rollover'. When you set the attributes for numbered members of a
collection, if there are more members than you have set the attributes
for, then the attributes will rollover. If you have set '[0].fillColor'
as red, '[1].fillColor' as green and '[2].fillColor' as blue, then the
fillColor for '[3]' would flip back to the start and become red, [4]
becomes green, and so on. (Actually, this isn't quite the case for the
standard pie chart since it has the first four fillColors set in the
base class, but this principle works in most other places).
</para>

<outlineAdd level="3">Adding New Attributes to a Collection</outlineAdd>
<para style="h3">Adding New Attributes to a Collection</para>

<para>

To add a new numbered attribute to a collection, simply enter a new
atrribute in the entry field.  For example, to add a new attribute
specifying the stroke width for the first pie slice:

</para>

<codesnippet language="python">
[0].strokeWidth = 1
</codesnippet>

<illustration width="320" height="313" align="CENTER">
<image file="images/collection_attributes_1.gif" x="0" y="0" width="245" height="316"/>
</illustration>


<outlineAdd level="2">Working with Legends</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Legends
</para>
<para>This section shows how to construct legends.  Legends are a little more involved
than most other chart components, in that they commonly need to pull other information
from other things on the drawing; their size and shape may depend on the number of
data series in a chart, which isn't always known at design time.  Legends have just undergone
an upgrade in December 2004 to allow them to 'connect to' and configure from the
charts they are attached to.</para>

<para>If you have a source distribution, the example charts herein will be located in
a subdirectory called 'samples' and are named as 'example_legend*.py'.  All of these
can be opened in the Drawing Editor, and directly executed to create a PDF output chart.
</para>
<para>The drawing below shows us getting started with a simple drawing containing a
vertical bar chart, title string, and Legend object.  The Legend has all the normal default values
EXCEPT THAT we have positioned it by setting x=220, y=20, and boxAnchor="southeast".
The latter choice means that the (220,20) reference point is at the bottom left of the legend.
When you first add the legend, you might not even see it as y = 0 and the legend 'grows down'
from the top of the drawing.
</para>
<drawing module="example_legend_1" function="LegendDrawing" baseDir="samples"/>

<para>The legend is, of course, the bit on the right with the multiple circles.  This does not
agree with the chart because, at the moment, it has no knowledge whatsoever of the
chart's existence.  </para>
<para>We'll just give a quick guided tour of the main attributes; we advise you to open up this
example in the drawing editor or to create one yourself and explore. A legend consists at minimum,
of a number of 'swatches' of colour, each with a string attached.  The overall position is
set with the<i> x</i>, <i>y </i>and <i>boxAnchor</i> attributes.  The actual data can be explicitly set through the <i>colorNamePairs</i>
attribute, if you wish.  Let's say we know there will be two series, and want to configure automatically.
</para>
<para>There are two main ways to get a legend working correctly.  First, you can explicitly
configure it.  If (as is very often the case), you know exactly how many series there will
be, and the labels to go with them, you could set this: </para>
<codesnippet language="python">colorNamePairs = [(red, 'widgets'), (green, 'sprockets')]</codesnippet>
<para>And you would then see a legend like this:</para>
<drawing module="example_legend_2" function="LegendDrawing" baseDir="samples"/>

<para>The other thing you may want to do is adjust the position of the swatches, especially
if there are a lot of them.  Pie charts might have a dozen or more.  The basic layout is to arrange them
in columns, up to a maximum numbe of swatches per column; the legend has an attribute <i>columnMaximum</i> with
default value 3, meaning that after 3 swatches are created it will start a new column.  If you had
twelve colorNamePairs entries and left the <i>columnMaximum</i> on 3, you would get 4 columns.

You can set this to a high number to arrange all your swatches vertically, or to 1 to force them to spread out horizontally.
There are also a number of attributes to specify the size of the swatch rectangle itself <i>(dx, dy)</i>,
the vertical and horizontal separation between swatches (<i>deltax, deltay</i>), the space between swatch
and text (<i>dxTextSpace</i>), and whether text appears to left or right of the swatches (<i>alignment</i>).
</para>

<para>Until v1.20 (Dec 2004) all swatches were simple rectangles, and a separate LineLegend would draw lines
with markers.  From Jan 2005 onwards, you are advised to use the plain old Legend class, and if you want
a different shape under direct control you can set the <i>swatchMarker</i> attribute.  For example,
if we assign as follows:
</para>
<codesnippet language="python">legend.swatchMarker = makeMarker('Circle')</codesnippet>
<para>...then we get circle shaped markers, and can then drill down into the marker object to further configure the size, colour, thickness etc.  The default kinds of Marker at present are <i>'Square', 'Diamond', 'Circle', 'Cross', 'Triangle', 'StarSix',
                                'Pentagon', 'Hexagon', 'Heptagon', 'Octagon', 'StarFive',
                                'FilledSquare', 'FilledCircle', 'FilledDiamond', 'FilledCross',
                                'FilledTriangle','FilledStarSix', 'FilledPentagon', 'FilledHexagon',
                                'FilledHeptagon', 'FilledOctagon', 'FilledStarFive',
                                'Smiley'</i></para>

<para>This kind of direct control is simple and should let a designer position a legend exactly the way they
want.  While it may seem perverse to set the shapes and colours yourself, it's also probably the simplest
way to do things in cases where there are many charts arranged on a drawing.</para>

<para style="h2">Connecting charts to legends</para>
<para>In other cases, one really wants the legend to intelligently connect to the chart and
configure itself, as the chart data might vary dramatically at runtime.  Two cases where you might
often want this are for Pie charts with many slices, where it's tedious to repeat a long list of
colour names and the number is variable; and for line charts with markers, where quite a lot
of attribute-setting would be needed to make the legend match the chart.
The new <i>Auto</i> feature
allows this to be done at several levels.   <i>(This has been added in a backward compatible
way and is therefore not very elegant - be warned!  In Version 2.0 we hope to reimplement
some attributes more sensibly)</i>.  To do things automatically, you must set the colorNamePairs
object to a new magic 'Auto' value, and tell it how to find the chart to configure itself from.
In the example below, we have switched to a LinePlot object called 'plot', and defined markers
for the lines.  The Drawing object can thus
refer to it as 'self.plot', and we pass this to the Auto object as follows:
</para>
<codesnippet language="python">colorNamePairs = Auto(chart=self.plot)</codesnippet>
<para>That's the main thing we need to do - the chart now picks up the number and colour for each series,
and draws the lines.  It cannot yet say anything more intelligent than 'series 0' and 'series 1' for the series names.
We'll cover this in a moment.
</para>
<drawing module="example_legend_4" function="LegendDrawing" baseDir="samples"/>

<para>The problem is that until now we have had no need for any 'series name' in the chart
classes.  We've added a hidden attribute to most of the charts so you can set this if
you wish, and legends can pull it out.  Each chart has an collection attribute, whose name
regrettably varies, for saying how each series should appear; for a bar chart this is
called 'bars', for a pie it is 'slices' and for a line plot it is 'lines'.  If one drills into this in
the editor, one can set these on specific series by typing "[n].name='myname'" for series n.
Defining two of these will result in the following chart:</para>

<codesnippet language="python">self.plot.lines[0].name = 'sprockets'
self.plot.lines[1].name = 'widgets'</codesnippet>
<drawing module="example_legend_5" function="LegendDrawing" baseDir="samples"/>






<nextPage/>
<outlineAdd level="2">Working with Colours</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Colours
</para>
<para>
Our graphics framework supports the RGB and CMYK color models
as well as specific spot colours.  The examples so far have
all involved attributes like 'red' and 'yellow', which
actually refer to RGB colours.    Here's what
we have done so far when editing a color:
</para>
<illustration width="245" height="316" align="CENTER">
<image file="images/gui_pic10.gif" x="0" y="0" width="245" height="316"/>
</illustration>

<para>Some users prefer to use CMYK colours
while others,for example web designers, may want a specific RGB value.  Here are the things
you could type into the line currently saying 'yellow':
</para>

<para>For the RGB model, with each number from 0 to 255, we use
the standard <i>Color</i> class from <i>reportlab.lib.colors</i>: </para>
<codesnippet language="python">fillColor = Color(128,0,0)</codesnippet>
<para>People used to writing HTML documents may find &quot;HTML-style&quot; colors useful:</para>
<codesnippet language="python">fillColor = toColor('#FF0000')</codesnippet>
<para>For the CMYK model, with each number ranging from 0 to 1, we use the
class <i>CMYKColor</i>:</para>
<codesnippet language="python">fillColor = CMYKColor(1.00,0,0.83,0.47)</codesnippet>
<para>Many people in the graphics world think in percentages and like to
specify a range from 0 to 100.  We therefore have a <i>PCMYKColor</i> class
as well - the 'P' standard for 'Percentage' - which is exactly
the same except for the numeric range:</para>
<codesnippet language="python">fillColor = PCMYKColor(100,0,83,47)</codesnippet>

<para><i>CMYKColor</i> and <i>PCMYKColor</i> accept the <i>spotName</i> and
<i>density</i> attributes. In our core open source model, they don't
do anything and are ignored when we write Postscript, but an additional (commercial) renderer
will know what to do with this information.  So we can now
specify an "Institutional Green" if we wish, or do inks of
varying densities:</para>

<codesnippet language="python">CMYKColor(1.00,0,0.83,0.47,spotName='PANTONE 349 CV',density=1.00)</codesnippet>

<para><b>Finally and most usefully, we can just define some constants
in an external file.</b>  Create a module called, say,  "yourcolors.py",
and put in on the Drawing Editor's search path somewhere (for example in
<i>rlextra/graphics/guiedit</i>).  In it we can put named constants like this:
</para>
<codesnippet language="python">
from reportlab.lib.colors import CMYKColor

#Your Company's Institutional colors
InstGreen = CMYKColor(1.00,0,0.83,0.47,spotName='PANTONE 349 CV',
                      density=1.00)
InstKhaki = CMYKColor(0.32,0.23,0.51,0.07,  spotName='PANTONE 875 CV',
                      density=1.00)
</codesnippet>

<para><i>the Drawing Editor</i> will find these colors, and you can use them just like
the standard ones.  We suggest that where required each department creates a module of
their own like this.<i>Warning:  don't try to redefine 'red', and don't
define the same name in more than one module; we don't want to promise
which definition would be found and used.</i></para>


<outlineAdd level="2">Working with Fonts</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Working with Fonts
</para>
<para>Diagra can use exactly the same fonts
in all output formats.  It uses Type 1 fonts and needs
an AFM and a PFB file for each. We covered their installation
earlier.  If creating fonts outside of the 'standard 14'
(Times/Helvetica/Courier with bold and italic, Symbol and ZapfDingbats),
you may need to add a couple of lines when rendering a drawing.</para>

<para>
To use a Type 1 font (<i>aka</i> a Postscript font), you will need at least two files. So for example, for the font
Avenir you could have files including:</para>
<codesnippet language="python">
aeblo___.PFB
aebl____.PFB
aeblo___.AFM
aebl____.AFM
</codesnippet>

<condPageBreak height="84"/>
<para style="noindent"><b>AFM file</b></para>
<para>The AFM file is the 'Adobe font metrics' file.
The AFM file contains important info about the characters in the font
(the 'glyphs'). This includes information such as their height, width,
info on the bounding box, hints and kerning and other things that are collectively known
as the 'font metrics'. It is vital to have the AFM file if you want to
use any ReportLab software to embed fonts.
</para>

<condPageBreak height="84"/>
<para style="bullet" bulletText="l">
If you don't have the AFM file for an Adobe font, you can get them from
the Adobe site. </para>
<pre style="mock_link">ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/</pre>
<para style="bullet" bulletText="l">To find the Adobe package number, you can check their type catalogue:</para>
<pre style="mock_link">http://www.adobe.com/type/main.html</pre>

<condPageBreak height="84"/>
<para style="noindent"><b>PFB file</b></para>
<para>
The PFB file is the 'printer outline file' or 'Printer Font Binary'.
The PFB file is used by our software if you need to produce bitmaps
(by setting 'formats' to be gif, jpg etc), and to produce the previews
in EPS files.</para>

<condPageBreak height="84"/>
<para style="noindent"><b>PFM files</b></para>
<para>
You may also see PFM files. The PFM file is the 'metrics file' or
'Printer Font Metrics' file. Essentially, this is a reduced version of
the AFM file. Most of the information our software needs is missing
from this file.
</para>

<para>
Once you have these files, they have to be located somewhere where our software can find them.
</para>
<para>
If you look in the file rl_config.py (located in the
Python22/reportlab/ directory), you will find a section that looks something like this:
</para>
<codesnippet language="python">
# places to look for T1Font information

T1SearchPath =  ('c:/Program Files/Adobe/Acrobat 5.0/Resource/Font', #Win32, Acrobat 5
                 'c:/Program Files/Adobe/Acrobat 4.0/Resource/Font', #Win32
                 '%(disk)s/Applications/Python %(sys_version)s/reportlab/fonts', #Mac?
                 '/usr/lib/Acrobat5/Resource/Font', #Linux, Acrobat 5?
                 '/usr/lib/Acrobat4/Resource/Font', #Linux
                 '%(REPORTLAB_DIR)s/fonts' #special
                 )
</codesnippet>
<para>
If you have extra fonts that you want to use and embed, you have two
choices. You can edit the rl_config.py file and add the existing directory
where your AFM and PFB files are located to this section. Or, you could add
your font files to one of these directories which the Diagra software already
know about. A good one is
'%(REPORTLAB_DIR)s/fonts' (i.e. C:\Python22\reportlab\fonts on a
standard PC installation).
</para>

<para>
Typically, if you are running in a server environment, you'd put the AFM and PFB files
in the fonts directory under the reportlab installation. If
you are running in a desktop environment, it might be easier for you
to add your font directories to the section in rl_config.py instead.
</para>

<para>
Once you have done all this, you can then use any of these fonts from
the Drawing Editor. Anything which has a 'fontName' attribute can be given the
name of one of these fonts. (If in doubt, the name we use is the
same as the one which appears in the AFM file on the line which begins 'FontName').
</para>

<condPageBreak height="84"/>
<outlineAdd level="2">Formats and Formatters</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Formats and Formatters
</para>

<outlineAdd level="3">DecimalFormatter</outlineAdd>
<para style="h3">DecimalFormatter</para>

<para>
In any place in a chart where you might require a format, you can use
the decimal formatter. The most obvious examples are the
<i>barLabelFormat</i> and <i>valueAxis.labelTextFormat</i> in a bar chart.
</para>

<para>
What you would do is find the correct line in the
window, highlight it so that you can edit it in the Drawing Editor's text entry
field, and replace the text after the equals sign with
'DecimalFormatter()'. Don't forget the brackets at the end!
You should then see something which resembles one of these lines
(though of course the details would change with the location):
</para>

<codesnippet language="python">
barLabelFormat   = DecimalFormatter(places=2, decimalSep='.',
                                    thousandSep=None,
                                    prefix=None,
                                    suffix=None)
valueAxis.labelTextFormat    = DecimalFormatter(places=2,
                                                decimalSep='.',
                                                thousandSep=None,
                                                prefix=None,
                                                suffix=None)
</codesnippet>

<para>
This then allows you to do things like change the decimal separator
from a full stop to a comma (to have numbers appearing in the
continental style of '1,00' rather than '1.00'), and add a prefix (for
things like '$' and '£') or suffix (for things like '%'). This also allows you to
specify how many numbers should appear after the decimal point (or
comma) - this is set by the 'places' attribute.
</para>

<spacer length="12"/>
<condPageBreak height="36"/>
<outlineAdd level="3">NA_Label and naLabel</outlineAdd>
<para style="h3">
NA_Label and naLabel
</para>

<para>
In some circumstances, you will have a chart which takes data from a
database which contains nulls (i.e. total empty cells which return a
'None' value to Python or a 'Null' value to SQL). By default, these
cells are ignored (so, for example, no bar and barLabel appear for
them in a bar chart which instead just leaves a gap where the bar
should be).
</para>

<para>
This isn't always what you want. The required behaviour may be to
leave out the bar but to insert a label which says 'n/a' (or 'results
not in' or some other snippet of text).
</para>

<para>
This is what the attribute <i>naLabel</i> is designed for. A number of
the charts have an attribute called <i>nalabel</i> . Initially, this starts off as:</para>
<codesnippet language="python">
naLabel          = None
</codesnippet>
<para>
You should change this to read
</para>
<codesnippet language="python">
naLabel          = NA_Label()
</codesnippet>
<para>
The Drawing Editor should then expand it to read something like:
</para>
<codesnippet language="python">
naLabel          = NA_Label(BarChartLabel)
</codesnippet>

<para>
These na_labels start of as Times-Roman with a fillColor of black and
the text being 'n/a'. They do not start with the same formatting as
your normal barLabels, and use their own separate formatting, which
allows you to set them to a different colour or style if you want them
to stand out.
</para>

<para>
<b>NB</b>: These labels only get used for cells which return Null (or
None). '0' is often a perfectly valid piece of data, so if you want
your chart to display these na_labels in these situations, you should
change the behaviour of your database to returns nulls rather than
zeroes in these locations.
</para>


<spacer length="12"/>
<condPageBreak height="36"/>
<outlineAdd level="3">Format Strings</outlineAdd>
<para style="h3">
Format Strings
</para>

<para>
You will probably be using format strings in a number of places when
you use the Drawing Editor to create or modify charts. As an example, here is a
fileNamePattern taken from a DataAwareDrawing. (DataAwareDrawings are
designed to pull data from a data source and produce multiple files
using this data, and their fileNamePattern allows us to do give them
distinct names which share a common root).
</para>

<codesnippet language="python">fileNamePattern = 'drawing%03d'</codesnippet>

<para>
The '%' sign means that we are using a <i>format string</i>. Anyone
who has used C's sprintf() format or is familiar with string
formatting in Python will recognise this. The 'd' in this case stands
for 'decimal' (i.e. a decimal integer). Others you may (rarely) want
to use include 'f' for a floating point number, 'o' for octal, 'x' or
'X' for hexadecimal, 'i' for integer (identical to 'd'), and 's' for string.
The '03' refers to a zero fill - in this case to three digits. If you use 'f',
the chartId is converted to a floating point number, and you can use a
'.' between two numbers to specify a field width and a precision.
</para>

<para><i>Examples:</i> </para>
<para>
The following examples assume that we are using chartIds of 1, 2, 3
and that we are only producing PDF output:</para>

<blockTable style="ExampleTableStyle" colWidths="3.5cm,10cm">
<tr>
<td><para><b>fileNamePattern</b></para></td><td><para><b>result</b></para></td>
</tr><tr>
<td><codesnippet language="python">drawing%d</codesnippet></td>
<td><codesnippet language="python">drawing1.pdf, drawing2.pdf, drawing3.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%03d</codesnippet></td>
<td><codesnippet language="python">drawing001.pdf, drawing002.pdf, drawing003.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%07d</codesnippet></td><td><codesnippet language="python">drawing0000001.pdf, drawing0000002.pdf,
drawing0000003.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%f</codesnippet></td><td><codesnippet language="python">drawing1.000000.pdf, drawing2.000000.pdf,
drawing3.000000.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%1.2f</codesnippet></td><td><codesnippet language="python">drawing1.00.pdf, drawing2.00.pdf, drawing3.00.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%s</codesnippet></td><td><codesnippet language="python">drawing1.pdf, drawing2.pdf, drawing3.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing%5.5f</codesnippet></td><td><codesnippet language="python">drawing1.00000.pdf, drawing2.00000.pdf,
drawing3.00000.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing3.2%f</codesnippet></td><td><codesnippet language="python">drawing3.21.000000.pdf, drawing3.22.000000.pdf,
drawing3.23.000000.pdf</codesnippet></td>
</tr><tr>
<td><codesnippet language="python">drawing03%d</codesnippet></td><td><codesnippet language="python">drawing031.pdf, drawing032.pdf, drawing033.pdf</codesnippet></td></tr>
</blockTable>

<para>
<b>NB</b> Notice how the last two are wrong: they both have the
numbers <i>before</i> the '%' sign rather than after it, so the
numbers are just treated as part of the alphanumeric filename prefix
rather than the formatting string. These examples all use 'drawing' as
this prefix, but you could of course have used 'Foobar' or anything
that you required.
</para>




<nextFrame/>
<outlineAdd level="1">Creating Data Aware Charts</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="5"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
Creating Data Aware Charts
</para>

<outlineAdd level="2">Introduction to DataAwareDrawings</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Introduction to DataAwareDrawings: Plotmode, fileNamePattern and outDir
</para>

<para>
The main difference between a static drawing and a data aware drawing
is that a data aware drawing inherits from the 'DataAwareDrawing' class (which
in turn inherits from 'Drawing'). In practice, you can do anything
with a DataAwareDrawing that you can with a Drawing, but it has a
number of additional abilities.
</para>

<para>
To start a DataAwareDrawing, start up the Drawing Editor, select 'New' from the
File menu and choose 'DataAwareDrawing' for the Base Class Name. Give
it a name - such as 'NewDataAwareDrawing'. This is also a blank canvas
in the same way that Drawing was.
</para>

<spacer length="6"/>
<illustration width="244" height="284" align="CENTER">
<image file="images/gui_pic12.gif" x="0" y="0" width="244" height="284"/>
</illustration>
<spacer length="12"/>

<para>The attribute window should contain something like the following:</para>
<codesnippet language="python">
EPS_info        = ('Dept', 'Your Company')
background      = None
chartId         = 0
dataSource      = DataSource(Widget)
fileNamePattern = 'drawing%03d'
formats         = ['eps', 'gif']
height          = 200
outDir          = '.'
preview         = 1
sampleData      = None
showBorder      = 0
test            = 0
transform       = (1, 0, 0, 1, 0, 0)
verbose         = 0
width           = 400
</codesnippet>

<spacer length="6"/>
<para><b>Plotmode</b></para>
<para>
One attribute that we didn't see when starting off with a Drawing was
the 'plotmode' (the line that looks like:</para>
<codesnippet language="python">formats         = ['eps', 'gif']</codesnippet>
<para>
This is the format that the output will appear in. The square brackets
around it show it is a list. Each item in it should be surrounded by
quotes. We can have multiple output formats (as long as the renderers can handle them).
</para>
<para>
Valid plotmodes are currently 'pdf', 'gif', 'png', 'tif', 'jpg', and 'eps'.
</para>

<spacer length="6"/>
<para><b>fileNamePattern</b></para>
<para>
DataAwareDrawings are designed to pull data from a data source and
produce multiple files using this data. Therefore we need to have some
sort of filename convention to tell them apart. The fileNamePattern
allows us to do this. The default of :
</para>
<codesnippet language="python">fileNamePattern = 'drawing%03d'</codesnippet>
<para>
will give each file a name in the form of 'drawing001'(plus a file
type suffix), 'drawing002', 'drawing003' and so on. You can edit this
to change both the prefix text and the number added to it.
</para>

<para>
The '%' sign means that we are using a <i>format string</i>. See
section 4.5 for more information about these.
</para>

<spacer length="6"/>
<para><b>outDir</b></para>
<para>
As well as changing the name of the files produces, you can change
where they are saved. The line
</para>
<codesnippet language="python">outDir          = '.'</codesnippet>
<para>
sets the output directory for these files to be the same as where the
script is. You can change this to a subdirectory, use '..' for
navigation back up the file system, and either give absolute or
relative path names.
</para>

<para><b>EPS_info</b></para>
<para>This only useful when producing EPS output. It contains the
Department and Company info that are inserted into the EPS header. It is
ignored if you use any other output format.
</para>

<para><b>background</b></para>
<para>This allows you to use a background for the whole drawing (not just a
chart inside the drawing). You can use any colour that we recognise
(look in reportlab\lib\colors.py and any other files where you have
defined colours such as perhaps yourcompany\yourcolors.py)
for lists of these. The RML2PDF has a good colorized list of these in
Appendix A("Colors recognized by RML")). The following is an example
of how to do one of these coloured backgrounds - this uses pink, but
you can use any colour. Once you have added the background, you should
see a new attribute appear in the attribute window which reads
'background = Rect(SolidShape)'. You can now double click on this to
change the colour, add a stroke color and stroke width (the stroke in
this case being an outline around the Drawing), and various other
attributes.</para>
<codesnippet language="python">background      = Rect(0,0,self.width, self.height, fillColor=pink, strokeColor=None)</codesnippet>
<para>As well as plain colours, you can also use other widgets. For
example, entering the following into the entry box</para>
<codesnippet language="python">background      = Grid()</codesnippet>
<para>gives you a grid as the background, whose attributes you can
then edit in the usual way (making it horizontal instead of vertical,
changing whether it uses coloured stripes or lines and so on).
</para>

<outlineAdd level="2">Setting the Data Source</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting the Data Source
</para>
<para>
A DataAwareDrawing can contain one (and only one) 'DataSource'.
Currently, all our data-aware classes use an ODBC database, but you
can use a CSV file - and eventually you would be able to use other
sources (such as an Excel spreadsheet).
</para>

<para>
For this example, you'll need to set up your database before you do
anything involving data in the Drawing Editor. We provide an example Access database
called 'sampledata.mdb'.  You should register it with the data
source name 'samplechartdata'. On a Windows machine, this involves
going to the Control Panel and selecting 'Data Sources (ODBC)' (or a
control panel  with a similar name, which may or may not be under
'Administrative Settings' depending on which version of Windows you
are using).
</para>

<para>
To make the chart connect to a database, you need to edit the line that reads
</para>
<codesnippet language="python">dataSource      = DataSource(Widget)</codesnippet>
<para>so that it reads</para>
<codesnippet language="python">dataSource      = ODBCDataSource()</codesnippet>

<para>
You should then see it change in the attributes window. You can then
double click on that line to set the various attributes of the
datasource. Once you have done this, the attribute window should look
something like this:
</para>

<codesnippet language="python">
associations   = Array(0, DataAssociation)
groupingColumn = 0
name           = 'samplechartdata'
password       = ''
sql            = 'SELECT * FROM generic_pie'
user           = ''
</codesnippet>

<para>
The <i>name</i> in this case is 'samplechartdata', though it
could be any name you have previously set up as an ODBC data source
with the OS.
</para>

<para>
If your ODBC datasource connection requires a username and password (for
instance if you're using SQL server without Windows Authentication),
you can append them to the datasource name separated by backslashes.  So
to connect to dsn 'mysqlserver' with username 'john' and password 'secret',
set the  dataSource.name property to 'mysqlserver/john/secret'
</para>


<para>
The <i>sql</i> attribute is the line of SQL(structured query language)
to be used to pull the data from the database. In most cases you can either use
</para>
<para style = "code_snippet" fontSize="8">
'SELECT * FROM <i>yourdatasource</i>'</para>
<para>
which gives your chart access to everything in the database (where
your datasource is the name of the datasource as given in
samplechartdata), or</para>
<para style = "code_snippet" fontSize="8">
'SELECT <i>columnname</i>, <i>columnname</i>, <i>columnname</i> FROM <i>yourdatasource</i>'</para>
<para>
which will only give you the specifically named columns from the
datasource - whether there are any other columns in the database or
not.
</para>


<outlineAdd level="2">Setting the Data Associations</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Setting the Data Associations
</para>

<para>
Once you have the data from the database, then you must define what to
do with it in your chart. This is what the data associations are for.
</para>

<para>
When you first start a data source, there are no data associations set up. Double-clicking on the
'dataSource  = ODBCDataSource(DataSource)' line brings up a set of
attributes in the attribute window which includes:</para>
<codesnippet language="python">associations   = Array(0, DataAssociation)</codesnippet>
<para>This shows that you have no data associations set-up yet. You can either
edit that line in place, and make the zero into the number of data
associations you will need, or double click on it, which will show you an attribute that says:
</para>
<codesnippet language="python">size = 0</codesnippet>
<para>where you can then edit the zero in the same way.</para>

<para>
Whichever way you do it, the size line then changes (e.g. to
'size = 4'), and you will see a number of lines in the pattern of:</para>
<codesnippet language="python">elementXX = DataAssociation(column=n, target=None, assocType='vector')</codesnippet>

<para>
The <i>column</i> is the position in the list of data retrieved by the SQL statement that we saw under the dataSource.
Notice how the count of columns starts a 0 rather than 1, and that column 0 is usually the chartId.</para>

<para>
So, for example, if the SQL was
</para>
<codesnippet language="sql">'SELECT chartId,numberOfBoxes,label,value FROM generic_slidebox'</codesnippet>
<para spaceAfter="0">then:</para>
<para style="bullet" bulletText="l">column 0 would be the data in the column of the database called 'chartId',</para>
<para style="bullet" bulletText="l">column 1 would be that of 'numberOfBoxes',</para>
<para style="bullet" bulletText="l">column 2 would be 'label' and,</para>
<para style="bullet" bulletText="l">column 3 would be 'value'.</para>
<para>Typically, column 0 is held by chartID which is used in setting the filename for the chart.</para>

<para>If you use a SQL statement which explicitly names the database columns
you want to retrieve in this way, it is less fragile and likely to break than one
where you pull everything using a '*'. If you use a 'SELECT * FROM' type SQL statement,
it will break if anyone inserts another column between two of yours
and changes the order of the columns you are retrieving. Naming them saves you from this risk.
</para>

<para>The <i>target</i> is the name of the variable in your chart that
this data should be plugged into. This should always be qualified by using
the name of the widget (or other object) where that variable is set.
So you would use 'PieChart.data' rather than just data (if you wanted
to set the data attribute in the widget PieChart), or 'chart.xValueAxis.labeltextFormat'
rather than just 'labeltextFormat' if you wanted to set the format of
the label text in the X-Axis of a linechart called 'chart'.</para>

<para>
And lastly, the <i>assocType</i> is the type of association used to
retrieve the data. You can pull single or multiple columns or rows
from a database or just a single cell. Valid values are
'scalar','vector','matrix', 'tmatrix' (from transformed matrix) and
'rowmap'. For more info on these, look in individual examples and the
following chapter ('More on Data Sources').
</para>


<nextFrame/>
<outlineAdd level="2">Example 1: Slidebox.py</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
A practical example: Slidebox.py
</para>


<para>
The previous descriptions were probably pretty confusing without any
solid examples to compare the against, so this section will rectify
that. We will work through 6 examples (which should be available in
rlextra/examples/graphics directory - those that work off the example
database use the have the suffix of _db.py). In all of these examples
you will see an example of what the finished chart looks like, along
with the data in the sample database and the Data Source and Data
Association lines.
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<plugInFlowable module="diagradocRmlPlugins" function="RMLSlideBox" baseDir="../../examples/graphics"></plugInFlowable>
<spacer length="12"/>

<para><b>Database Layout</b></para>

<blockTable style="DatabaseTopStyle"><tr><td>Table: </td><td>generic_slidebox</td></tr></blockTable>
<blockTable style="DatabaseStyle">
<tr>
<td>chartId</td>
<td>numberOfBoxes</td>
<td>label</td>
<td>value</td>
<td>title</td>
</tr>
<tr>
<td>1</td>
<td>7</td>
<td>source: Guinness</td>
<td>6</td>
<td>Beer Sales</td>
</tr>
<tr>
<td>2</td>
<td>7</td>
<td>source: Hoegaarden</td>
<td>5</td>
<td>Beer Sales</td>
</tr>
<tr>
<td>3</td>
<td>5</td>
<td>source: Youngs</td>
<td>4</td>
<td>Beer Sales</td>
</tr>
</blockTable>
<spacer length="12"/>

<para><b>Drawing Data Attributes</b></para>
<codesnippet language="python">
#Autogenerated by ReportLab guiedit do not edit
from rlextra.graphics.guiedit.datacharts import ODBCDataSource, DataAssociation, DataAwareDrawing
from reportlab.graphics.shapes import _DrawingEditorMixin
from reportlab.graphics.charts.slidebox import SlideBox

class SlideBoxDrawing(_DrawingEditorMixin,DataAwareDrawing):
	def __init__(self,width=400,height=200,*args,**kw):
		apply(DataAwareDrawing.__init__,(self,width,height)+args,kw)
		self._add(self,SlideBox(),name='SlideBox',validate=None,desc='The main chart')
		self.height         = 40
		self.width          = 168
		self.dataSource     = ODBCDataSource()
		self.dataSource.sql ='SELECT chartId,numberOfBoxes,label,value FROM generic_slidebox'
		self.dataSource.associations.size = 4
		self.dataSource.associations.element00 = DataAssociation(column=0, target='chartId', assocType='scalar')
		self.dataSource.associations.element01 = DataAssociation(column=1,
                                                                 target='SlideBox.numberOfBoxes',
                                                                 assocType='scalar')
		self.dataSource.associations.element02 = DataAssociation(column=2,
                                                                 target='SlideBox.sourceLabelText',
                                                                 assocType='scalar')
		self.dataSource.associations.element03 = DataAssociation(column=3,
                                                                 target='SlideBox.trianglePosition',
                                                                 assocType='scalar')
		self.verbose            = 1
		self.formats            = ['eps', 'pdf']
		self.outDir             = './output/'
		self.fileNamePattern    = 'slidebox%03d'


if __name__=="__main__": #NORUNTESTS
	SlideBoxDrawing().go()
</codesnippet>
<spacer length="12"/>

<condPageBreak height="84"/>
<para><b>Description</b></para>
<para>
This example can be found in the directory <font
face="courier">rlextra/examples/graphics</font>, with the filename of
<font face="courier">slidebox_db.py</font>. <font
face="courier">slidebox.py</font> is similar, but runs off a CSV file
rather than a database.
</para>

<para>
In this first real example, we have given you the whole code that
the Drawing Editor produces. For all of the other charts you will only be shown
the self.dataSource attributes (and you should never need to look at
the raw code if you are using the Drawing Editor). This chart is the simplest
(from a data standpoint), so we can both show you what the code looks
like in its raw state, and point out a few other pieces of information
at the same time.
</para>

<para spaceAfter="0">The are only three pieces of data that a slidebox chart requires:</para>
<para spaceBefore="0" spaceAfter="0"><i>numberOfBoxes</i>: the number of coloured and numbered boxes
 that make up this widget (in the example graphic above, it is
 7).</para>
<para spaceBefore="0" spaceAfter="0"><i>label</i>: the text that is displayed at the bottom right of
 the widget (in this case 'source: ReportLab')</para>
<para spaceBefore="0"><i>value</i>: the number where the triangle pointers should be displayed.</para>

<para>
Looking at the code of slidebox.py (in the 'Drawing Data Attributes'
section above), the first line we need to consider is
</para>
<codesnippet language="python">
self._add(self,SlideBox(),name='SlideBox',validate=None,desc='The main chart')
</codesnippet>
<para>
This is line that adds the widget 'SlideBox' to the basic
DataAwareDrawing. If we had been making this up from scratch, we could
have achieved the same thing by selecting 'Add New Widget' from the
Action menu, clicking on SlideBox in the list of widgets, and typing in
the name 'SlideBox' in the 'New Widget Name?' text box.
</para>

<para>
The 'self.height' and 'self.width' lines, as you would expect, set the
height and width of the resulting drawing. The 'self.dataSource' line sets
things up so that we can use a database as the source for our
data.</para>

<para>
The 'self.dataSource.sql' line shows the line of SQL we use to pull
this data. This looks in the table generic_slidebox in the database we
have already specified and retrieves, for each chart items from the columns named
'chartId', 'numberOfBoxes', 'label' and 'value'.</para>

<para>
The four lines that start 'self.dataSource.associations' set up what
to do with this data. Each of these has an assocType of 'scalar'.
Scalars are the simplest type of data association. They retrieve a single
cell from the database (actually a 1x1 matrix). So for each chart, we
retrieve the single element 'chartId' (which is not inserted into the
widget that we use to create the slidebox since it is used by
the DataAwareDrawing in constructing the filename), the single element
'numberOfBoxes' which is inserted into the 'numberOfBoxes' attribute of
the widget SlideBox, the element 'label' which is inserted into
sourceLabelText attribute of SlideBox, and the element 'value' which is
inserted into the attribute trianglePosition of the SlideBox widget.
You can see all these attributes when you double-click on the
'SlideBox = SlideBox(Widget)' line in the attributes window - it then
displays all the attributes for this widget.
</para>

<para>
When you are editing a drawing using the Drawing Editor, everything is static.
How can we tell if the data associations are correct? This is where
the 'sampleData' and the 'test' attributes come into action. If you set the
test attribute to be '1' (rather than the default '0'), it will test if
the data-aware parts of your drawing work. It connects to your data
source, fetches the data and applies the first block of data to the
drawing (i.e. in this case, uses the first row in the table). If it fails,
it gives you an error message in the Log window which should explain
what went wrong. So for example, if you have the dataSource name wrong
(or have forgotten to set it up with the OS), you would see something like this:</para>

<codesnippet language="python">
OperationalError: ('IM002', 0, '[Microsoft][ODBC Driver Manager] Data
source name not found and no default driver specified', 5896)
</codesnippet>

<para>
If everything works correctly, then the information from the first
block of data is used, the main window will change to reflect the new
status of the SlideBox widget, and the data itself is appears in the 'sampleData' attribute:
</para>

<codesnippet language="python">
sampleData      = [(1, 7, 'source: Guinness', 6)]
</codesnippet>

<para>
If you want to continue testing, you can use numbers higher than one
for the test attribute, and the drawing will fetch the corresponding
data and use it in the same way (as long as you don't overshoot the
end of the data in the data source).
</para>
<para>
The last attribute to mention before we talk about running this script
and creating the charts is 'verbose'. If verbose is set to 0, then
when you run it, the script is silent. It produces no text on your
screen confirming what it has done. If verbose is set to 1, then it
produces a message telling you when it has written each file. (These
messages may be very useful in testing, but less so on a server - you
can suppress them at will using this attribute).
</para>

<para>
The last line of the code is the one that makes the drawing 'active'.
DataAwareDrawing has a 'go' method - a piece of code that connects to
the specified data source, repeatedly fetches blocks of data, closes
the connection, and uses the data in the way you have specified. The
Drawing Editor inserts a call to this into your new drawing, so that
when you run it from the command line or the desktop it will
automatically do this. Guiedit automatically does this if the class
has a 'go' method to make it active - DataAwareDrawing has, but
Drawing doesn't. You should never have to insert this call by hand -
but it's worth knowing about.
</para>

<outlineAdd level="2">Running the resulting scripts</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
<b>Running the resulting scripts</b></para>
<para>
Once you have made any changes you want to the chart and then saved it
to a file, you can then execute it. To run the script that creates the
charts from this base chart, you need to drop back into the Operating
System. You can use Windows Explorer (or the Finder if you are on a
Mac) to find slidebox.py and double click on it.
</para>

<para>
You should see a window open and the following text appear in it:
</para>

<condPageBreak height="84"/>
<codesnippet language="python">
generating PDF file './output/slidebox001.pdf'
generating EPS file './output/slidebox001.eps'
generating PDF file './output/slidebox002.pdf'
generating EPS file './output/slidebox002.eps'
generating PDF file './output/slidebox003.pdf'
generating EPS file './output/slidebox003.eps'
</codesnippet>

<para>
Running slidebox.py has created an both an EPS chart and a PDF chart
for each chartID in our sample database. If you inspect them, you will
find that the data from the data source has been inserted into the
relevant places in the chart to produce the correct behaviour.</para>
<para>
<b>NB</b> This method of running the file with a double-click is
fine for Macintosh users, but may cause problems on a Windows system.
On a Mac, the dialogue box will stay on screen (with a title of
'terminated') once the program has finished running. On a Windows
system, the window appears, stays around for only as long as it takes
to run the program and then closes. If the program terminates due to
an error, an error message is displayed - but is not on screen long
enough to be visible. This is why for Windows users, we strongly
recommend starting the program from an MS-DOS console (available from
the start menu e.g. Start->Programs->Accessories->Command Prompt). Once
you have the console open, cd to the correct directory and start the
python script. For example:
</para>

<codesnippet language="python">
C:\python22\rlextra\examples\graphics
python slidebox_db.py
</codesnippet>

<para>
This way, if an error occurs you will definitely see the error message, and
are not in danger of having a directory full of last month's charts.
</para>

<nextFrame/>
<outlineAdd level="2">Example 2: Dotbox.py</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 2: Dotbox.py
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<plugInFlowable module="diagradocRmlPlugins" function="RMLDotBox" baseDir="../../examples/graphics"></plugInFlowable>
<spacer length="12"/>

<para><b>Database Layout</b></para>
<blockTable style="DatabaseTopStyle"><tr><td>Table:</td><td>generic_dotbox</td></tr></blockTable>
<blockTable style="DatabaseStyle">
<tr>
<td>chartId</td>
<td>dotx</td>
<td>doty</td>
<td>notes</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>Optional</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
<td>Notes</td>
</tr>
<tr>
<td>3</td>
<td>2</td>
<td>1</td>
<td>Not Interesting</td>
</tr>
<tr>
<td>4</td>
<td>1</td>
<td>3</td>
<td>Ignore this... unless you want to.</td>
</tr>
<tr>
<td>5</td>
<td>0</td>
<td>0</td>
<td></td>
</tr>
<tr>
<td>6</td>
<td>3</td>
<td>3</td>
<td></td>
</tr>
</blockTable>
<spacer length="12"/>

<para><b>Drawing Data Attributes</b></para>
<codesnippet language="python">
self.dataSource                   = ODBCDataSource()
self.dataSource.sql               = 'SELECT chartId,dotx,doty FROM generic_dotbox'
self.dataSource.groupingColumn    = 0
self.dataSource.associations.size = 3
self.dataSource.associations.element00 = DataAssociation(column=0, target='chartId',
                                                         assocType='scalar')
self.dataSource.associations.element01 = DataAssociation(column=1, target='DotBox.dotXPosition',
                                                         assocType='scalar')
self.dataSource.associations.element02 = DataAssociation(column=2, target='DotBox.dotYPosition',
                                                         assocType='scalar')
</codesnippet>

<condPageBreak height="84"/>
<para><b>Description</b></para>
<para>
The data to be fetched from the dataSource in this case is also all
scalars. So the single datum chartID is fetched and used by
DataAwareDrawing, dotx is retrieved from the dataSource and inserted
into the attribute dotXPosition in the widget DotBox, and doty is
inserted into DotBox's dotYPosition attribute.
</para>

<para>
Two other things to notice are that the dataSource can have columns
that are <i>not</i> referenced by any of the DataAssociations. You can
have data in the database that is used by other programs or
departments which doesn't affect the production of your charts in any
way (such as the 'notes' column in this example).
</para>

<para>
Conversely, the widget that constructs the charts in your
DataAwareDrawing can have attributes that are not data-aware, and
still have to be set manually using the Drawing Editor. In DotBox, the
labels are held in the xlabels and ylabels attributes. These are fixed
and not set by the dataSource.
</para>

<para>
In this specific chart, the number of divisions inside the actual 'dot
box' are set by the length of the list of labels. Using
</para>
<codesnippet language="python">
xlabels       = ['Value', 'Blend', 'Growth']
</codesnippet>
<para>
produced a dotbox where there are three boxes along the x axis, but
</para>
<codesnippet language="python">
xlabels       = ['Value', 'Blend', 'Growth', 'Something else']
</codesnippet>
<para>
will produce one with four along this axis. If you set either of these
attributes to 'None' you will get an error, so if you want to remove
the labels for one of these DotBoxes, you need to do something
like:</para>
<codesnippet language="python">
xlabels       = [None, None, None]
</codesnippet>
<para>
which removes the labels but keeps the rest of the structure.
</para>

<para>
Other things that we can mention about Dotbox include
previews and borders.
</para>
<para style="bullet" bulletText="l"><b>Preview</b></para>
<para style="bullet">
This controls whether your EPS files have a (cross-platform) TIFF
image embedded as a preview. The default is 1 - they are on. If you
need small file sizes set this to 0. If the number is greater than 1,
the previews are enlarged. This makes the file sizes a lot bigger.
This has no effect on output formats other than EPS.
</para>

<para style="bullet" bulletText="l"><b>showBorder</b></para>
<para style="bullet">
If you are only using PDF output, you can use the showBorder
attribute. Set this to 1, and it will add a border around the edge of
your widget. For historical reasons, this doesn't work with EPS.
</para>
<para style="bullet">
One way to add a border that works in both PDF and EPS is to add the following:
</para>
<codesnippet language="python">
background = Rect(0,0,self.width, self.height, fillColor=None, strokeColor=black, strokeWidth=1)
</codesnippet>

<nextFrame/>
<outlineAdd level="2">Example 3: Horizontalbarchart.py</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 3: Horizontalbarchart.py
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<plugInFlowable module="diagradocRmlPlugins" function="RMLHorizontalBarChart" baseDir="../../examples/graphics"></plugInFlowable>
<spacer length="12"/>

<para><b>Database Layout</b></para>
<blockTable style="DatabaseTopStyle"><tr><td>Table:</td><td>generic_bar</td></tr></blockTable>
<blockTable style="DatabaseStyle">
<tr>
<td>chartId</td>
<td>rowId</td>
<td>name</td>
<td>value1</td>
<td>value2</td>
<td>value3</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>Widgets</td>
<td>17</td>
<td>25</td>
<td>32</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>Sprockets</td>
<td>19</td>
<td>28</td>
<td>35</td>
</tr>
<tr>
<td>1</td>
<td>3</td>
<td>Thingummies</td>
<td>13</td>
<td>20</td>
<td>30</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>Doodahs</td>
<td>20</td>
<td>29</td>
<td>21</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>Dohickies</td>
<td>11</td>
<td>12</td>
<td>11</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>Thingamajigs</td>
<td>32</td>
<td>17</td>
<td>12</td>
</tr>
<tr>
<td>2</td>
<td>4</td>
<td>Oojamaflips</td>
<td>14</td>
<td>15</td>
<td>21</td>
</tr>
<tr>
<td>3</td>
<td>1</td>
<td>Type1</td>
<td>12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>2</td>
<td>Type2</td>
<td>6</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>Type3</td>
<td>2</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>4</td>
<td>Type4</td>
<td>20</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>5</td>
<td>TypeX</td>
<td>12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>6</td>
<td>TypeXI</td>
<td>15</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>7</td>
<td>TypeXII</td>
<td>25</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>8</td>
<td>Unknown</td>
<td>8</td>
<td></td>
<td></td>
</tr>
</blockTable>
<spacer length="12"/>

<para><b>Drawing Data Attributes</b></para>
<codesnippet language="python">
self.dataSource = ODBCDataSource()
self.dataSource.sql = 'SELECT chartId, name, value1, value2 FROM generic_bar'
self.dataSource.associations = Array(4, DataAssociation)
self.dataSource.groupingColumn = 0
self.dataSource.associations.element00 = DataAssociation(column=0,
                                                         target='chartId',
                                                         assocType='scalar')
self.dataSource.associations.element01 = DataAssociation(column=1,
                                                         target='HorizontalBarChart.categoryNames',
                                                         assocType='vector')
self.dataSource.associations.element02 = DataAssociation(column=[2],
                                                         target='HorizontalBarChart.data',
                                                         assocType='tmatrix')
self.dataSource.associations.element03 = DataAssociation(column=3,
                                                         target='HorizontalBarChart.labelRow2',
                                                         assocType='vector')
</codesnippet>


<condPageBreak height="84"/>
<para><b>To Remove the Labels</b></para>
<codesnippet language="python">
HorizontalBarChart.labelRow2     = None
HorizontalBarChart.labelData     = None
HorizontalBarChart.categoryNames = None
</codesnippet>
<para spaceBefore="0" spaceAfter="0">
<i>change element01 and element03 in the dataSource.associations so that the target=None:</i></para>
<codesnippet language="python">
element01 = DataAssociation(column=1, target='None', assocType='vector')
element03 = DataAssociation(column=3, target='None', assocType='vector')
</codesnippet>

<condPageBreak height="84"/>
<para><b>Description</b></para>
<para>
A number of new things are introduced in this chart. The first one is
the groupingColumn. Since each chart of this type uses data from more
than one row in this table, our DataAwareDrawing needs to know which rows go together.
The groupingColumn attribute is what provides this information. In this case (and most cases),
the grouping column is '0' - the first one in the row (like many of the other attributes of
our chart classes, counting these starts at 0). So, all the
rows which have a chartID of 1 go into the same chart (Widgets,
Sprockets, and Thingummies), all those whose chartID is 2 go into
another and so on.
</para>

<para>
Unlike the previous two chart types, we have more than one assocType
in this chart. We can now see both 'vector' and 'tmatrix' Data Associations in action.
</para>

<para><b>vector</b></para>
<para>
self.dataSource.associations.element01 takes a vector of column 1 and
places this in the categoryNames attribute of the HorizontalBarChart
widget.
</para>

<para>
Since this vector is specified as a single number (rather than a
list - it's not surrounded by square brackets), it returns a column
of data for that chart. So, for a chartId of '1', it returns:
</para>
<codesnippet language="python">
['Widgets', 'Sprockets', 'Thingummies']
</codesnippet>
<para>which become the categoryNames (the labels on the far left).</para>

<para>
Shown as a diagram, this looks like this - the column outlined in red
is the what is being placed into categoryNames. Note that we are only showing the
columns that the SQL retrieved from the database, not all the columns
that actually are in the database as above.
</para>
<spacer length="6"/>

<blockTable style="DatabaseStyleEx2A">
<tr>
<td>chartId</td>
<td>name</td>
<td>value1</td>
<td>value2</td>
</tr>
<tr>
<td>1</td>
<td>Widgets</td>
<td>17</td>
<td>25</td>
</tr>
<tr>
<td>1</td>
<td>Sprockets</td>
<td>19</td>
<td>28</td>
</tr>
<tr>
<td>1</td>
<td>Thingummies</td>
<td>13</td>
<td>20</td>
</tr>
</blockTable>

<para>
self.dataSource.associations.element03 (the other vector) also does
this, but for column 3 in the data rather than for column 1).</para>

<para><b>tmatrix</b></para>
<para>
self.dataSource.associations.element02 takes a tmatrix ('transform
matrix') of column 2 and places it into the 'data' attribute of the widget
HorizontalBarChart.
</para>

<para>
The column specified is a list with one item in it ('[2]'), so the tmatrix returns:</para>
<codesnippet language="python">((17.0, 19.0, 13.0),)</codesnippet>

<para>This can be imagined as the Data Association taking this red column:</para>
<blockTable style="DatabaseStyleEx2B">
<tr>
<td>chartId</td>
<td>name</td>
<td>value1</td>
<td>value2</td>
</tr>
<tr>
<td>1</td>
<td>Widgets</td>
<td>17</td>
<td>25</td>
</tr>
<tr>
<td>1</td>
<td>Sprockets</td>
<td>19</td>
<td>28</td>
</tr>
<tr>
<td>1</td>
<td>Thingummies</td>
<td>13</td>
<td>20</td>
</tr>
</blockTable>

<para>and converting it into this before passing it on:</para>

<blockTable style="DatabaseStyleEx2C">
<tr>
<td>17</td>
<td>19</td>
<td>13</td>
</tr>
</blockTable>

<spacer length="12"/>

<para>
It is also possible to specify more than one column by using a list
with more than one item in it. If we used ('[2,3]'), the tmatrix would return:</para>
<codesnippet language="python">((17, 19, 13), (25, 28, 20))</codesnippet>

<para>
This can be thought of as taking these columns:
</para>
<blockTable style="DatabaseStyleEx2D">
<tr>
<td>chartId</td>
<td>name</td>
<td>value1</td>
<td>value2</td>
</tr>
<tr>
<td>1</td>
<td>Widgets</td>
<td>17</td>
<td>25</td>
</tr>
<tr>
<td>1</td>
<td>Sprockets</td>
<td>19</td>
<td>28</td>
</tr>
<tr>
<td>1</td>
<td>Thingummies</td>
<td>13</td>
<td>20</td>
</tr>
</blockTable>

<para> and converting them to:</para>

<blockTable style="DatabaseStyleEx2E">
<tr>
<td>17</td>
<td>19</td>
<td>13</td>
</tr>
<tr>
<td>25</td>
<td>28</td>
<td>20</td>
</tr>
</blockTable>


<para>Both vectors and tmatrices can be a lot more complex than this - see chapter 6 for more details on that.</para>


<para>
Other things of note include:
</para>

<para style="bullet" bulletText="l">
<b>Axes</b>
</para>

<para style="bullet">
Most charts will be implemented using axes - whether they are visible or not.
</para>
<para style="bullet">
The chart HorizontalBarChart has two axes - the valueAxis (the one
along the bottom), and the categoryAxis (the one up the side). In this chart,
they are both invisible. Both these axes have the following attributes:
</para>
<codesnippet language="python">
visible
visibleAxis
visibleTicks
</codesnippet>

<para style="bullet">
The <i>visibleAxis</i> attribute controls whether the actual axis is
drawn - i.e. the main line that the ticks hang off. The
<i>visibleTicks</i> controls whether those ticks are displayed. The
other attributes that control the ticks are
<i>tickUp</i>/<i>tickDown</i> in the valueAxis, and
<i>tickLeft</i>/<i>tickRight</i> in the categoryAxis. Unlike the 'visible' attributes
we have just mentioned, these tick-related attributes are not Boolean.
These 'tick' attributes take a number which is the length of the tick.
An easy mistake to make is to set visibleTicks to 1, but have both
tickLeft and tickRight set to 0. In this case, the ticks are
displayed, but you can't see them due to them having a zero length.
</para>

<para style="bullet">
The <i>visible</i> attribute controls whether anything axis-related is
drawn at all. This over-rides the other attributes - you might have
visibleAxis set to 1, but if visible is set to 0, then it won't be
displayed.
</para>

<para style="bullet">
(For more information about how to use Axes, look in section 5 of the
ReportLab Graphics Guide, available on our web site at
http://www.reportlab.com/download.html)
</para>

<para style="bullet" bulletText="l"><b>reverseDirection</b>
</para>
<para style="bullet">
This attribute is under the categoryAxis (i.e. it's HorizontalBarChart.categoryAxis.reverseDirection).
It is available to all bar charts. As its name implies, if
this is set to 1, it reverses the direction of the plot. The bars and
their barLabels are then drawn in the order opposite to the way they are
laid out in the data (e.g. [1,2,3] is reversed to [3,2,1]). This
allows you to change if the bars are drawn from the bottom up or the
top down (inside a chart).
</para>

<para style="bullet" bulletText="l"><b>labelRow2</b>
</para>
<para style="bullet">
This is an attribute available only to this particular chart (i.e.
<i>rlextra/examples/graphics/horizontalbarchart_db.py</i>).
What is does is allows you to have an optional second row of labels
appearing to the right of the main labels. If labelRow2 is None or an
empty list then no these labels do not appear.
</para>

<para style="bullet">
labelRow2 uses the same format as the main labels (the attribute
<i>labelFormat</i>). For information on using format strings, look in
section 4.5 (Formats and Formatters) in the chapter on 'Working with Charts'.
</para>

<para>
Like the other bar charts, the horizontalbarchart also has a number of
attributes relating to the 'line'. The attributes <i>lineLength</i>,
<i>lineStrokeWidth</i> and <i>lineColor</i> all refer to it. This line
is the thin, horizontal line which goes from the tip of the actual bar
to the labels on the right hand side. LineLength controls how long it
is, lineColor controls what colour it is and lineStrokeWidth controls
its width.
</para>

<nextFrame/>
<outlineAdd level="2">Example 4: Verticalbarchart.py</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 4: Verticalbarchart.py
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<plugInFlowable module="diagradocRmlPlugins" function="RMLVerticalBarChart"  baseDir="../../examples/graphics"></plugInFlowable>
<spacer length="12"/>

<para><b>Database Layout</b></para>
<blockTable style="DatabaseTopStyle"><tr><td>Table:</td><td>generic_bar</td></tr></blockTable>
<blockTable style="DatabaseStyle">
<tr>
<td>chartId</td>
<td>rowId</td>
<td>name</td>
<td>value1</td>
<td>value2</td>
<td>value3</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>Widgets</td>
<td>17</td>
<td>25</td>
<td>32</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>Sprockets</td>
<td>19</td>
<td>28</td>
<td>35</td>
</tr>
<tr>
<td>1</td>
<td>3</td>
<td>Thingummies</td>
<td>13</td>
<td>20</td>
<td>30</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>Doodahs</td>
<td>20</td>
<td>29</td>
<td>21</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>Dohickies</td>
<td>11</td>
<td>12</td>
<td>11</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>Thingamajigs</td>
<td>32</td>
<td>17</td>
<td>12</td>
</tr>
<tr>
<td>2</td>
<td>4</td>
<td>Oojamaflips</td>
<td>14</td>
<td>15</td>
<td>21</td>
</tr>
<tr>
<td>3</td>
<td>1</td>
<td>Type1</td>
<td>12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>2</td>
<td>Type2</td>
<td>6</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>Type3</td>
<td>2</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>4</td>
<td>Type4</td>
<td>20</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>5</td>
<td>TypeX</td>
<td>12</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>6</td>
<td>TypeXI</td>
<td>15</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>7</td>
<td>TypeXII</td>
<td>25</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>8</td>
<td>Unknown</td>
<td>8</td>
<td></td>
<td></td>
</tr>
</blockTable>
<spacer length="12"/>

<para><b>Drawing Data Attributes</b></para>
<codesnippet language="python">
self.dataSource = ODBCDataSource()
self.dataSource.sql     = 'SELECT chartId, name, value1, value2 FROM generic_bar'
self.dataSource.groupingColumn = 0
self.dataSource.associations   = Array(3, DataAssociation)
self.dataSource.associations.element00 = DataAssociation(column=0,
                                         target='chartId',
                                         assocType='scalar')
self.dataSource.associations.element01 = DataAssociation(column=[2,3],
                                         target='VerticalBarChart.data',
                                         assocType='tmatrix')
self.dataSource.associations.element02 = DataAssociation(column=1,
                                         target='VerticalBarChart.categoryAxis.categoryNames',
                                         assocType='vector')
</codesnippet>

<condPageBreak height="84"/>
<para><b>To Remove the Labels</b></para>
<codesnippet language="python">
VerticalBarChart.categoryAxis.categoryNames   = None
VerticalBarChart.barLabelFormat               = None
</codesnippet>
<para spaceBefore="0" spaceAfter="0">
<i>to remove the labels in the legend - change this line (in VerticalBarChart.legend):</i>
</para>
<codesnippet language="python">
colorNamePairs = [(PCMYKColor(100,65,0,30,spotName='PANTONE 288 CV'), 'Fund'),
                  (PCMYKColor(11,11,72,0,spotName='PANTONE 458 CV'), 'Index')]
to:
colorNamePairs = [(PCMYKColor(100,65,0,30,spotName='PANTONE 288 CV'), None),
                  (PCMYKColor(11,11,72,0,spotName='PANTONE 458 CV'), None)]
(i.e. change the strings inside the single quotes into 'None'(No quotes))
</codesnippet>
<para spaceBefore="0" spaceAfter="0">
<i>change element02 in the dataSource.associations so that the target=None:</i>
</para>
<codesnippet language="python">
element02 = DataAssociation(column=1, target=None, assocType='vector')
</codesnippet>

<condPageBreak height="84"/>
<para><b>Description</b></para>

<para>
Like the other bar charts, VerticalBarChart has a <i>reverseDirection</i> attribute.
In this case it is under self.VerticalBarChart.categoryAxis.reverseDirection.
</para>

<para>
Under VerticalBarChart.barLabels are a number of attributes to do with
the labels at the tops of the bars (the ones that the 'lines' lead
to). VerticalBarChart.barLabels.angle is the angle that these labels
are printed at - in this case 90<super>o</super>. The <i>dx</i> and <i>dy</i>
attributes refer to the horizontal and vertical shifts that are
applied to these labels away from the bars they refer to. A negative
number moves it down/to the left of its bar, and a positive number
moves it up/to the right. (For more details on these, refer to section
5.3 ('Labels') of the Graphics Guide and consult any autogenerated
reference that you have).
</para>

<para>While we are discussing barcharts, this is the place to mention three attributes of the valueAxis:</para>
<para style="bullet" bulletText="l"><i>valueMin</i></para>
<para style="bullet" bulletText="l"><i>valueMax</i></para>
<para style="bullet" bulletText="l"><i>forceZero</i></para>

<spacer length="12"/>
<para><b>valueMin and ValueMax</b></para>
<para>
If you <i>know</i> that your data will <i>always</i> be in a certain
range, you can use <i>valueMin</i> and <i>valueMax</i>. ValueMin sets as an absolute
the lowest value that will appear on the chart, and this always
appears at the bottom of the chart. ValueMax does the same thing at
the top of the chart (Of course, if you are using a horizontal
barchart then top and bottom become left and right). If you don't
absolutely know the boundaries of your data, then it is best to avoid
using these. If you use them anyway, you may well find yourself in a
situation where the bars flow outside the chart and its axes.
</para>

<para>
Given the above warning, <i>valueMin</i> and <i>valueMax</i> can be used to fix the
position of an axis. If the values to be used are a mixture of
positive and negative numbers, and you have not set the <i>valueMin</i> and
<i>valueMax</i>, the axis will 'float' up and down  - i.e. it will appear in
different places in different charts, as dictated by the data. Setting
these attributes can avoid this.
</para>

<para>
As an example, for the above chart if you decided to set the <i>valueMin</i>
and <i>valueMax</i> to 40, you would see the following lines appear in the
source window:
</para>

<codesnippet language="python">
        self.VerticalBarChart.valueAxis.valueMax           = 40
        self.VerticalBarChart.valueAxis.valueMin           = 40
</codesnippet>

<spacer length="12"/>
<para><b>forceZero</b></para>

<para>
When the <i>valueMin</i> and <i>valueMax</i> haven't been set, the chart will set
its own lower and upper limits. For example, if your data ranges from
50 to 100, the lower limit the chart chooses will be around 50. This
can be misleading. ForceZero forces the lower limit to be 0, so the
heights of the bars and the scaling are in a more straightforward
proportion to each other. If you start getting unusual behaviour in
your charts, try setting forceZero to 1 and seeing what effect this
has.
</para>

<para>
ForceZero takes a boolean argument - 1 sets it to 'on' and forces zero
to appear on the value axis, 0, sets it to 'off' and allows the chart
to omit zero. You can right click on the <i>forceZero</i> attribute in the
attributes window of the Drawing Editor to set this.
</para>

<para>
As an example, if you decided to use <i>forceZero</i> for the above chart you
would see this appear in the source window:
</para>

<codesnippet language="python">
        self.VerticalBarChart.valueAxis.forceZero          = 1
</codesnippet>

<para>
These two examples both have the same data set, but the one on the left
has forceZero off, and the one on the right has it on. Other than this
forceZero attribute, these are the same chart.
</para>

<plugInFlowable module="diagradocRmlPlugins" function="RMLForceZeros" baseDir="../../examples/graphics"></plugInFlowable>

<nextFrame/>
<outlineAdd level="2">Example 5: Linechart.py</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 5: Linechart.py
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<codesnippet language="python">Line chart example would go here</codesnippet>
<!-- <plugInFlowable module="diagradocRmlPlugins" function="RMLLineChart" baseDir="."></plugInFlowable>-->
<spacer length="12"/>

<para><b>Database Layout</b></para>
<blockTable style="DatabaseTopStyle"><tr><td>Table:</td><td>generic_time_series</td></tr></blockTable>
<blockTable style="DatabaseStyle">
<tr>
<td>chartId</td>
<td>date</td>
<td>value1</td>
<td>value3</td>
<td>value2</td>
</tr>
<tr>
<td>119</td>
<td>02/12/1997</td>
<td>1.00</td>
<td></td>
<td>1.00</td>
</tr>
<tr>
<td>119</td>
<td>31/12/1997</td>
<td>1.00</td>
<td></td>
<td>1.00</td>
</tr>
<tr>
<td>119</td>
<td>31/01/1998</td>
<td>1.00</td>
<td></td>
<td>1.01</td>
</tr>
<tr>
<td>119</td>
<td>28/02/1998</td>
<td>1.02</td>
<td></td>
<td>1.02</td>
</tr>
<tr>
<td>119</td>
<td>31/03/1998</td>
<td>1.01</td>
<td></td>
<td>1.01</td>
</tr>
<tr>
<td>119</td>
<td>30/04/1998</td>
<td>1.03</td>
<td></td>
<td>1.02</td>
</tr>
<tr>
<td>119</td>
<td>31/05/1998</td>
<td>1.03</td>
<td></td>
<td>1.02</td>
</tr>
<tr>
<td>119</td>
<td>30/06/1998</td>
<td>1.03</td>
<td></td>
<td>1.03</td>
</tr>
<tr>
<td>119</td>
<td>31/07/1998</td>
<td>1.03</td>
<td></td>
<td>1.03</td>
</tr>
<tr>
<td>119</td>
<td>31/08/1998</td>
<td>1.02</td>
<td></td>
<td>1.05</td>
</tr>
<tr>
<td>119</td>
<td>30/09/1998</td>
<td>1.05</td>
<td></td>
<td>1.09</td>
</tr>
</blockTable>
<blockTable style="DatabaseTopStyle"><tr><td> . . . </td></tr></blockTable>
<blockTable style="DatabaseContinuationStyle">
<tr>
<td>666</td>
<td>31/07/1992</td>
<td>1.03</td>
<td></td>
<td>1.13</td>
</tr>
<tr>
<td>666</td>
<td>31/08/1992</td>
<td>1.04</td>
<td></td>
<td>1.14</td>
</tr>
<tr>
<td>666</td>
<td>30/09/1992</td>
<td>1.04</td>
<td></td>
<td>1.14</td>
</tr>
<tr>
<td>666</td>
<td>31/10/1992</td>
<td>0.99</td>
<td></td>
<td>1.19</td>
</tr>
<tr>
<td>666</td>
<td>30/11/1992</td>
<td>1.05</td>
<td></td>
<td>1.25</td>
</tr>
<tr>
<td>666</td>
<td>31/12/1992</td>
<td>1.06</td>
<td></td>
<td>1.16</td>
</tr>
<tr>
<td>chartId</td>
<td>date</td>
<td>value1</td>
<td>value3</td>
<td>value2</td>
</tr>
</blockTable>
<spacer length="12"/>


<condPageBreak height="84"/>
<para><b>Drawing Data Attributes</b></para>
<codesnippet language="python">
self.dataSource      = ODBCDataSource()
self.dataSource.sql  = 'SELECT chartId, date, value1*100, value2*100, value3*100 FROM generic_time_series'
self.dataSource.associations   = Array(2, DataAssociation)
self.dataSource.associations.element00 = DataAssociation(column=0,
                                                         target='chartId',
                                                         assocType='scalar')
self.dataSource.associations.element01 = DataAssociation(column=[[1, 2], [1,3], [1,4]],
                                                         target='chart.data',
                                                         assocType='tmatrix')
</codesnippet>

<condPageBreak height="84"/>
<para><b>Description</b></para>

<para>As standard in this chart class, there is the facility to take
up to three lines from the data and plot them. If the column in the
data is empty, it is ignored. To see an example of this, type in
'test=3' into the entry field - the chart graphic in the main the
Drawing Editor window will change to one that uses the three columns
of data from the table generic_time_series in sampledata.mdb
</para>

<para>
If you look under dataSource.associations, you will see the following line:
</para>
<codesnippet language="python">
element01 = DataAssociation(column=[[1, 2], [1, 3], [1, 4]],
                            target='chart.data',
                            assocType='tmatrix')
</codesnippet>

<para>
In the chart data, the date (column 1 - the second column in the database) is
used to provide the x-coordinate in sets of x-y pairs, which are then
plotted as a line. Here is an example of what the data looks like when
it is inserted into chart.data - this is from test three again:
</para>

<codesnippet language="python">
(
    ((19971202, 100.0), (19971231, 100.3), ... (20000630, 114.6),  (20000731, 113.6)),
    ((19971202, 100.0), (19971231, 101.0), ... (20000630, 133.58), (20000731, 132.60)),
    ((19971202, 100.0), (19971231, 107.0), ... (20000630, 123.58), (20000731, 122.60))
)
</codesnippet>
<para style="footer">Sections omitted for brevity - indicated by '...'</para>


<spacer length="12"/>
<para><b>Adding more lines</b></para>
<para>
If three lines are not enough, you can add extra lines to this chart.
To add them, first change the SQL under self.dataSource from:
</para>
<codesnippet language="python">
sql = 'SELECT chartId, date, value1*100, value2*100, value3*100
                                          FROM generic_time_series'
</codesnippet>
<para>to</para>
<codesnippet language="python">
sql = 'SELECT chartId, date, value1*100, value2*100, value3*100, value4*100
                                          FROM generic_time_series'
</codesnippet>
<para> adding as many extra as you need. Then change the element under dataSource.associations from :</para>
<codesnippet language="python">
element01 = DataAssociation(column=[[1, 2], [1, 3], [1, 4]],
                            target='chart.data',
                            assocType='tmatrix')
</codesnippet>
<para>to</para>
<codesnippet language="python">
element01 = DataAssociation(column=[[1, 2], [1, 3], [1, 4], [1,5]],
                            target='chart.data',
                            assocType='tmatrix')
</codesnippet>

<para>
Make sure you have enough columns in your database, otherwise you will
get an error message when you try to test or run it:</para>
<codesnippet language="python">
  Traceback (most recent call last):
  File "c:\Python22\rlextra\graphics\guiedit\datacharts.py", line 572, in testConnect
    self.applyDataSet(sample)
  File "c:\Python22\rlextra\graphics\guiedit\datacharts.py", line 646, in applyDataSet
    y = row[c]
IndexError: tuple index out of range
</codesnippet>


<spacer length="12"/>
<para><b>Removing lines</b></para>
<para>
The first and most obvious approach is to remove them from the
database. If a column in the database is empty, the chart will ignore
it.
</para>
<para>
A second way to change the data association so that the data isn't
being used. E.g., to plot only one line, no matter what else is in the
database, change:</para>
<codesnippet language="python">
element01 = DataAssociation(column=[[1, 2], [1, 3], [1, 4], [1,5]],
                            target='chart.data',
                            assocType='tmatrix')
</codesnippet>
<para>to</para>
<codesnippet language="python">
element01 = DataAssociation(column=[[1, 2]], target='chart.data', assocType='tmatrix')
</codesnippet>

<para>
yet another way of doing it is to change the SQL. For example, change:
</para>

<codesnippet language="python">sql = 'SELECT chartId, date, value1*100, value2*100, value3*100 FROM generic_time_series'</codesnippet>
<para>to</para>
<codesnippet language="python">sql = 'SELECT chartId, date, value1*100, null, value3*100 FROM generic_time_series'</codesnippet>

<para>The <i>null</i> in the SQL acts as a placeholder - it sits in your SELECT statement but is ignored.</para>

<spacer length="12"/>
<para><b>Changing the colour of the lines (and other line attributes)</b></para>
<para>All the attributes to do with the lines in this chart are found under chart.lines.
This is a collection of attributes - see section 4.4 Working with Collections for
more general info about Collections.</para>

<para>
If a line begins with the actual attribute name, then it applies to all the lines in the chart. So
</para>

<codesnippet language="python">
strokeWidth = 1
</codesnippet>

<para>
sets the width of every line (or at least every line that is plotting
data) to 1 point. If a line starts with a number inside square
brackets, then it only applies to that one line. So
</para>

<codesnippet language="python">
[1].strokeColor = ChbkYellow
</codesnippet>

<para>
changes the colour of the <i>second</i> line to the colour we have
previously defined as ChbkYellow (since we count from 0). This happens
to be the chartbook yellow we have imported from the file
xxxcolors.py, but it could be any color that reportlab.graphics
recognises.
</para>

<para>
If you set colours for a number of lines, and the actual number of
lines on the chart is greater than that, the colours will 'rollover'.
If you set chart.lines.[0]strokeColor to red and
chart.lines.[1]strokeColor to blue, then proceed to actually have four
lines plotted on your chart, then the first line will be red, the
second blue, the third red again, and the fourth blue again.
</para>

<para>
One attribute that is a slightly harder to explain is the
strokeDashArray. If you want to have a dotted or dashed line on your
chart, you do this using the strokeDashArray. You give this an
argument of a list of numbers (e.g. '[5,2]' or '[4,2,8,2]'). The first
number is the number of points that that dash will be on for, the second
is the number of points it will be off for. More complex patterns of
numbers will produce more complex sequences of dots dashes.
</para>
<spacer length="12"/>

<para>
The attributes under chart.lines are:
</para>
<codesnippet language="python">
strokeDashArray
strokeWidth
strokeColor
</codesnippet>

<spacer length="12"/>
<para><b>Other attributes</b></para>

<para style="bullet" bulletText="l">reversePlotOrder</para>
<para style="nobullet">
This controls the order in which lines are plotted over each other. If
the line which is most important in the data is appearing underneath
all the others change this from 0 to 1 (or vice versa). This appears
under the attributes for the chart.</para>

<para>The following attributes are found under chart.yValueAxis:</para>

<para style="bullet" bulletText="l">requiredRange</para>
<para style="nobullet">
The <i>requiredRange</i> is the least range that should be displayed.
For example, if you have data which ranges from -1.2 to 0.75, if the
chart is left to set its own limits these will look like very big
swings. Giving a required range of 30 would (in this case) give you a
range of -15 to +15 and put the numbers into perspective. The default
value for requiredRange for this chart is 30.</para>


<para style="bullet" bulletText="l">leftAxisPercent</para>
<para style="nobullet">
<i>leftAxisPercent</i> controls whether or not a percentage sign ('%')
is added to the end of labels. It can be set to 0 or 1.
</para>

<para style="bullet" bulletText="l">leftAxisOrigShiftIPC and leftAxisOrigShiftMin</para>
<para style="nobullet">
These both refer to the lowest tick on the left axis of the chart. If it is 100 (or
whatever your baseline is), it can require a 'shift' so that it
doesn't appear on the bottom line of the grid. If you want this shift
to take place, you need to set one of these attributes. Both perform
the shift, but they differ on how it is specified.
<i>leftAxisOrigShiftIPC</i> specifies it as a ration (IPC = 'In Per Cent'), and
<i>leftAxisOrigShiftMin</i> specifies it an as amount.
</para>

<para style="bullet" bulletText="l">SkipLL0</para>
<para style="nobullet">
In some situations, you don't want the first tick label on the axis to
appear. Setting <i>SkipLL0</i> to 1 is used to skip this first tick label.
</para>

<nextFrame/>
<outlineAdd level="2">Example 6: SectorCylinderChart</outlineAdd>
<para style="h2">
<getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Example 6: SectorCylinderChart
</para>

<para><b>Example Chart</b></para>
<spacer length="6"/>
<plugInFlowable module="diagradocRmlPlugins" function="RMLSymbolCylinderChart" baseDir="../../examples/graphics"></plugInFlowable>
<spacer length="12"/>

<para><b>Description</b></para>
<para>
This example is mainly here to show you how to use a couple of
attributes that haven't been mentioned so far.
</para>

<para>
All barcharts have the attribute of <i>Symbol</i>. This is used where
you want a bar to be represented by a graphic rather than the default
rectangle that bars use. You can use:
</para>

<codesnippet language="python">
Symbol = ShadedRect(Widget)
</codesnippet>

<para>
This then allows you access to the attributes under Symbol and so
allows you to use various shading effects. Initially, you
can set the start and end colours, which does pretty much as you would
expect - the shading starts with the start colour, shades through the
number of gradations set in the <i>numShades </i> attribute and then
finishes with the end colour.
</para>

<para>
You can then go on to set the <i>cylinderMode</i> attribute. Set to 0,
this gives you a simple shade (as we've just described). Set it to 1,
and it shades from the start colour to the end colour and then
back to the start colour again, giving the illusion of a cylinder.
</para>

<para>
You can set the <i>orientation</i> of the shading using the attribute
of the same name. This can be set to 'horizontal' or 'vertical'.
Horizontal has the gradation going from top to bottom, vertical has
it going from side to side.
</para>

<para>
Another attribute you can set is <i>style</i> (under
chart.categoryAxis). If you set this to 'parallel', having more than
one series in the chart data produces bars which are side by side (as
we saw in the verticalbarchart.py in example 5). If you set this to
'stacked', the behaviour is different. Multiple series in the data
lead to having bars which are stacked on top of each other
(or different coloured divisions of a single bar, if that's the way
you see it).
</para>

<para>
Putting all these attributes together allows you to create a chart like the example above.
</para>

<nextFrame/>
<outlineAdd level="1">More about Using Axes</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="6"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
More about Using Axes
</para>

<para>
This section provides a pseudo-code description of the order in which
various attributes are used in the most commonly used axis - 'ValueAxis'.
This can be useful when trying to debug a
new chart class or when figuring out how one works.
</para>

<para>
It also gives brief descriptions of some attributes which only appear
in these axes (such as leftAxisOrigShiftIPC, and leftAxisSkipLL0).
</para>

<para>
Don't feel that you have to understand everything in this section.
Feel free to skip it. The best way to understand how these work is by
using them, or by experimenting with them in the Drawing Editor. This is more for
use when you can't figure out why something is going wrong, rather
than just figuring out how it works at all.
</para>


<outlineAdd level="2">ValueAxis</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
ValueAxis</b>
</para>

<codesnippet>
<![CDATA[

ValueAxis:
setPosition (called by the containing chart)
    set the _x, _y & _length attributes passed from
    above
configure(data)  (called by the containing chart)
    _setRange
        compute _valueMin and _valueMax
        either from valueMin, valueMax or directly from the data.
        if _valueMin == _valueMax:
            force in a fake range of unit length.
        if forceZero:
            ensure _valueMin <= 0 <= _valueMax
        _rangeAdjust:
            do nothing method to allow hooking at this point
    _calcScaleFactor
        _scaleFactor=(_valueMax-_valueMin)/_length
    _calcTickmarkPositions
        if self.valueSteps is set:
            _tickValues = valueSteps
        else
            _calcValueStep
                if valueStep is set
                    _valueStep = valueStep
                else
                    rawRange = _ValueMax-_valueMin
                    n = min(maximumTicks-1, _length/minimumTickSpacing
                    rawInterval = rawRange/n
                    _valueStep = nextRoundNumber(rawInterval)
            ticks = []
            t = int(_valueMin/_valueStep)*_valueStep
            if t>=_ValueMin: append tick to ticks
            t += _valueStep
            while t<=_valuemax:
                append t to ticks
                t += _valueStep
            _tickValues = ticks
        _adjustAxisTicks
            in the base class this is a null hook method
            client classes can override to adjust the tick mark
            positions
    _configured = 1

draw
    if visible
        makeAxis
            if visibleAxis
                determine join from joinAxisMode, joinAxisPos and joinAxis
                draw the axis line

        makeTicks
            if visibleTicks
                for tick in _tickValues:
                    v = scaled tick
                    draw tick line using up/down and the scaled value

        makeTickLabels
            for tick _tickValues
                v = scaled tick
                if labelTextFormat is a string use as a format
                    txt = labelTextFormat % tick
                elif labelTextFormat is a list
                    txt = labelTextFormat[i] (i = tick sequence num)
                elif labelTextFormat is callable
                    txt = labelTextFormat(tick)
                else arise value error
                draw the label using the scaled value v
                and using the labels[i] styles
]]>
</codesnippet>

<para>
NB: in the above if <i>_valueMin</i> and <i>_valueMax</i> are calculated from the data
nothing forces them to be nice numbers so that then the axis may not start
or end on tick values.
</para>

<condPageBreak height="36"/>
<!--  outlineAdd level="2">BongoYValueAxis</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
BongoYValueAxis</b>
</para>

<para>
This is a vertical version of a value axis and has some extra
attributes namely <i>requiredRange</i>, <i>leftAxisPercent</i>,
<i>leftAxisOrigShiftIPC</i>, <i>leftAxisOrigShiftMin</i> and
<i>leftAxisSkipLL0</i>. The <i>requiredRange</i> is the least range
that should be displayed. <i>leftAxisPercent</i> controls whether a
'%' is added to the end of labels. It can probably be subsumed into
the <i>labelTextFormat</i>. The <i>ShiftIPC</i> and <i>ShiftMin</i>
refer to the shift of the lowest tick required if that tick is 100. The <i>IPC</i> is the fraction of the tick interval and the
<i>Min</i> is the least required shift. <i>SkipLL0</i> is used to skip
the first tick label.
</para>

<para>
The extra functionality is achieved by overriding the base class hook method
_rangeAdjust.
</para>

<codesnippet language="python">
<![CDATA[

_rangeAdjust:
    if requiredRange and _valueMax-_valueMin<requiredRange:
        adjust _valueMin, _valueMax to get at least the requiredRange
        try to get the lowest value onto 100 (or zero).

    get ticks, T and labels L using the old fashioned ticks routine passing in
        _valueMax, _valueMin, leftAxisPercent and valueStep
        the ticks will be spaced at valueStep if that is set.

    labelTextFormat = L as a list this will be used directly (no formatting etc)
    _valueMin = T[0]
    _valueMax = T[-1]
    _valueSteps = T

    if _valueMin==100:
        _calcValueStep(from the base class) to ensure that _valueStep is set
        m = max(leftAxisOrigShiftIPC*_valueStep,
            leftAxisOrigShiftMin*(_valueMax-_valueMin)/_length)
        # this is the shift
        _valueMin = _valueMin + m  the min value is now not on a tick
    if leftAxisSkipLL0:
        labelTextFormat[0] = ''  delete first label
]]>
</codesnippet>

<para>NB:
if <i>valueStep</i> isn't set and <i>_valueMin</i> is calculated as 100 in the above
then it seems as though we do an unwanted <i>_calcValueStep</i> i.e. we appear
to be using the wrong <i>_valueStep</i> in the shift calc. I think in practice
this isn't very important, but logically we should set
_valueStep = T[1]-T[0].
</para>
-->

<nextFrame/>
<outlineAdd level="1">More on Data Sources</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="7"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
More on Data Sources
</para>

<outlineAdd level="2">
Making a Simple Chart Data Aware</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/> Making a Simple Chart Data Aware</b>
</para>
<para>As an example, we are going to create a simple bar chart and
make it pull data from the example Access Database (unpack sampledata.mdb from
the file rlextra/examples/graphics/sampledata.zip). We'll assume you have set up
the ODBC connection and that the name is 'samplechartdata'.</para>

<para>
Start the Drawing Editor, and select 'New' from the File menu. When the 'New
Project parameters' dialog box appears, select 'DataAwareDrawing',
give it a name ('SampleDataChart'), and click on OK. Select 'Add New
Widget', click on 'HorizontalBarChart', give it a name ('chart') and click on OK.
</para>

<para>Click on <font face="Courier">chart =
HorizontalBarChart(BarChart)</font>, and change the x to be 75 and y
to be 30 so it's a bit further from the edge.
</para>

<para>
Select 'Add New Widget' again, type in "String(125, 124, 'I am a
string')" (since String has to be given its x and y coordinates and
some text), give it a name ('title') and click on OK.
</para>

<para>
So far we have just set up a basic static bar chart.
The rest of this example will be concerned with making it data aware.
</para>

<spacer length="6"/>
<!--full size:-->
<!--illustration width="408" height="546"-->
<!--image file="images/databarchart1.gif" x="0" y="0" width="408" height="546"/-->
<!--at 60%:-->
<illustration width="245" height="328">
<image file="images/databarchart1.gif" x="0" y="0" width="245" height="328"/>
</illustration>
<spacer length="12"/>

<para spaceAfter="0">
Find the line that says
</para>
<para style="code_snippet">dataSource      = DataSource(Widget)</para>

<para spaceAfter="0">
Click on it, and change it so that it reads
</para>
<para style="code_snippet">dataSource      = ODBCDataSource()</para>

<para spaceAfter="0">
In the attributes window it will change so that it now reads</para>
<para style="code_snippet">dataSource      = ODBCDataSource(DataSource)</para>

<para>
Double click on the data source line, and the attributes window will
change to show you the dataSource attributes. Normally, you would have
to change the 'name' line to point to the correct ODBC data source,
but in this example file the default name is the correct one.
</para>

<para>
If you were using a stored procedure, you would also have to set the
'password' and 'user' attributes while you were here as well.
</para>

<para spaceAfter="0">
Change the sql line to read
</para>
<para style="code_snippet">sql = 'SELECT chartId, rowId, name, value1, value2, value3 FROM generic_bar'</para>

<para>
This line tells the chart where to get the data from. In this
case it is selecting the columns called chartId, rowId (and so on) from
the table called generic_bar in our Access database. We can get these
names by looking at the table in the database and choosing which
columns we need to use.
</para>

<para>
The groupingColumn is the column that we will use to decide which data will be in a
chart. It might typically a fund name or ID, but could be anything.
What matters is that it is the same for each element that will go in a
single chart, but will not be repeated in other charts.
</para>

<para>
We do not have to change this, since it will remain as 0. When
counting the columns, we start counting at 0 (as programmers do).
Therefore, column 0 is the first one we retrieve in the SQL - chartId.
</para>

<para>
For this to actually allow us to do anything useful, we must associate
it with the chartId of the chart. And to do this, you must change the
number of Data Associations to something greater than 0.
</para>

<para spaceAfter="0">
Double-click on the line that says
</para>
<para style="code_snippet">associations   = Array(0, DataAssociation)</para>

<para spaceAfter="0">you should now see a line that says</para>
<para style="code_snippet">size = 0</para>

<para>Change this 0 to a number 4, and you will see a number of new
lines appear, each one looking something like this:</para>

<para style="code_snippet">element00 = DataAssociation(column=0, target=None, assocType='vector')</para>

<para>
Now we can make our first attribute data aware. Click on the first line 'element' line, and change it to read
</para>

<para style="code_snippet">element00 = DataAssociation(column=0, target='chartId', assocType='scalar')</para>

<para>You can either change it in the text edit box below the
attributes window, or you can double click on it and change each element separately.</para>

<para>The column number is the number of the column in the SQL
statement that we set earlier. As already mentioned, 0 is the first
column in the list in the SQL statement - chartId. Target is where
that item of data is going to be 'plugged-into' in our chart. In this
case, it's at the top level, so we can just type in 'chartId' without
having to say which part of the chart it refers to.</para>

<para spaceAfter="0">
This line should now read:</para>
<para style="code_snippet">element00 = DataAssociation(column=0, target='chartId', assocType='scalar')</para>

<para>
If you go back to the top level of the chart, you can type
'test=1' into the entry field and hit enter. The chartId will change
to 1. Nothing on the chart itself will change yet, since we haven't
plumbed any of it in yet, but it's enough to show you that the chart
is pulling data from the database.
</para>

<para>
Now we can make the title data aware. Normally, you would have a
separate field for the title, but in this example we are just going to
use the name of the first column. To do this, double click on
DataSource, then on associations to get you back into the attribute
for self.dataSource.associations. Click on <font face="courier">element01</font>, and edit it so it reads</para>

<para style="code_snippet">
element01 = DataAssociation(column=2, target='title.text', assocType='scalar')
</para>

<para>
The pulls the data from column 2 (the third column) in the SQL
statement and fits it in as a single item into the attribute text of
title (the String we added earlier).
</para>

<para>Sometimes the best way of finding out what kind of data
association is required for a chart is to look at the sample data it
uses as a default, and see which kind of data association produces
that kind of output. Then you can figure out which columns (or rows)
from the database you need to specify.
</para>

<para>
We have seen scalars in use - here is a quick run down of the other
data associations:</para>

<para spaceAfter="0"><b>scalar</b></para>
<para>We have already seen what a scalar is - it's basically just a
single variable. You can think of it as a 1x1 matrix if you want, but
basically it's just a single box which is pulled from the database and
fitted into a single slot in the chart.
</para>
<para spaceAfter="0">Examples of something we can use a scalar for:</para>
<codesnippet language="python">
text       = 'Widgets'
x          = 125
</codesnippet>

<para spaceAfter="0">Typical use for a scalar:</para>
<para spaceBefore="0">String.text, Label.text, chartId</para>

<para spaceAfter="0"><b>vector</b></para>
<para>
Vectors are useful when you need to pull a column of data from a
database, and use all of it (or at least all that is in that set, as
defined by the groupingColumn).
</para>

<para>
If you give a single number for the column, then one column will be returned as a
list (it will be surrounded by brackets). So, for something like this:
</para>
<codesnippet language="python">
DataAssociation(column=1, target='HorizontalBarChart.categoryNames',
                assocType='vector')
</codesnippet>
<para>
you might get something back looking like this:
</para>
<codesnippet language="python">
['Widgets', 'Sprockets', 'Thingummies']
</codesnippet>

<para spaceAfter="0">Examples of something we can use a vector with a single number for:</para>
<codesnippet language="python">
categoryNames     = ('Cash', 'Other', 'Italy', 'Switzerland')
labelRow2         = [5.3, 3.3, 2.4, 4.5]
</codesnippet>

<para>
If you give a more than one number for the column, they must be
separated by a comma and enclosed in square brackets. Then the data
association will return a list (enclosed by square brackets)
containing tuples of the columns (enclosed by parentheses).
</para>

<para>For something like this:</para>
<codesnippet language="python">
DataAssociation(column=[1, 2], target='data', assocType='vector')
</codesnippet>
<para>
you might get something back looking like this:
</para>
<codesnippet language="python">
[('a01', 'a02'), ('a11', 'a12'), ('a21', 'a12'), ('a11', 'a12')]
</codesnippet>

<para spaceAfter="0">Examples of something we can use a vector with a numbers in square brackets for:</para>
<codesnippet language="python">
data         = [('a01', 'a02'), ('a11', 'a12'), ('a21', 'a12'), ('a11', 'a12')]
</codesnippet>

<para spaceAfter="0">Typical use for a vector:</para>
<para spaceBefore="0">chart categoryNames, horizontal barchart data, pie chart data and legend names</para>


<para spaceAfter="0"><b>matrix</b></para>

<para>
Matrices aren't very often used. More often you will be using a tmatrix (see below).
</para>
<para>
For a description of a matrix, look in section 7.3 (Data Association Types)
</para>

<para spaceAfter="0"><b>tmatrix</b></para>

<para>
A tmatrix is a 'transformed matrix'. It is used to convert a vertical
column (or columns) into a horizontal list.
</para>
<para>
The most common use is where the column is given as a single number
inside square brackets (a list), the tmatrix returns a tuple inside another
tuple (parentheses inside other parentheses). So for something like
this:</para>
<codesnippet language="python">
column=[13], target='data', assocType='tmatrix'
</codesnippet>
<para>
You might get back something looking like this:
</para>
<codesnippet language="python">
((0.6, -1.3, -0.7, -0.4),)
</codesnippet>

<para spaceAfter="0">Examples of something we can use a tmatrix with a
single number for (as seen in the default data):</para>
<codesnippet language="python">
data             = ((0.0, -0.10, 0.0, 0.3, 0.3),)
data             = [(3.5, 15.5, 6.0, 7.5)]
</codesnippet>

<para>For charts where you need two data sets (e.g., where you are
plotting one set of bars against another), the column specification
would be two numbers inside the square brackets:</para>
<codesnippet language="python">
column=[8, 7], target='data', assocType='tmatrix'</codesnippet>
<para>
would give you something like:
</para>
<codesnippet language="python">
data            = ((-10.9, -7.1, 2.9), (9.6, 13.2, 29.5, -6.2))
</codesnippet>

<para spaceAfter="0">Typical use for a tmatrix:</para>
<para spaceBefore="0">chart.data (for various barcharts)</para>


<para spaceAfter="0"><b>rowmap</b></para>
<para>Rowmap is seldom used. It used for picking out individual cells
in a row and stringing them together, rather than selecting a whole
column.</para>

<para spaceAfter="0">Typical use for a rowmap:</para>
<para spaceBefore="0">chart.data</para>

<para>If you need more information and examples on any one of these
data associations, read section 7.3.</para>

<spacer length="12"/>

<para>The sample data in our example barchart looks like this:</para>
<codesnippet language="python">
data             = [(100, 110, 120, 130), (70, 80, 85, 90)]
</codesnippet>

<para>So, it is a possibility that it is either a vector or a tmatrix.
Since tmatrices are used for the chart data for barcharts, we can use one of them.
</para>

<para>
Looking at the SQL statement will tell us what we need to plot and what positions it is in.
</para>
<para style="code_snippet">sql = 'SELECT chartId, rowId, name, value1, value2, value3 FROM generic_bar'</para>

<para>We can see that we have value1, value2 and value3 to plot on this chart, in positions 3, 4 and 5.</para>

<para>So we need to change a data association to read</para>
<codesnippet language="python">
element02 = DataAssociation(column=[3,4,5], target='chart.data',
                            assocType='tmatrix')
</codesnippet>

<para>The last thing we will do is to will do is set up a data
association for the bar category names (the names at the left of each
group of bars).</para>

<para>The names appear the third column of the data, so (since we
count from 0) this becomes a column specification of 2:
</para>
<codesnippet language="python">
element03 = DataAssociation(column=2,
                            target='chart.categoryAxis.categoryNames',
                            assocType='vector')
</codesnippet>

<para>Going to the top level and doing test=1 (or 2 or 3) shows us
that the it works and is pulling data for the chart, the title and the
category labels from the database.</para>

<para>This example is saved as the file <font
face="Courier">rlextra/examples/graphics/sampleDataBarChart.py</font> if you wish
to play with it further.</para>

<para>There are a number of other things you can do to make it better
- making it verbose so you can see it saving the files when you run it
from the command line, changing the fileNamePattern, changing the bar
colours so they look better and so on. However, it is data aware and
works, so anything else doesn't really belong in this section.</para>


<condPageBreak height="72"/>
<outlineAdd level="2">
Changing the Data Associations on an Existing Chart</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/> Changing the Data Associations on an Existing Chart</b>
</para>

<para spaceAfter="0">
There may be a number of ways you need to change the data associations on an
existing chart. You may need to:
</para>
<para style="bullet" bulletText="l" spaceAfter="0">Add a new column and data association, </para>
<para style="bullet" bulletText="l" spaceAfter="0">Remove an existing column and data association</para>
<para style="bullet" bulletText="l" spaceAfter="0">Change an existing column and data association in place</para>
<para style="bullet" bulletText="l" spaceAfter="0">Change the input to a stored procedure</para>


<spacer length="12"/>

<para spaceAfter="0"><b>Adding a new column and data Association</b></para>

<para>
If someone has added an extra column to the database (or altered the
stored procedure to return an extra column), and you need to make us
of it, you need to do the following.
</para>

<para style="bullet" bulletText="l" spaceAfter="0">Edit the SQL to add in the new item, </para>
<para style="bullet" bulletText="l" spaceAfter="0">Add a new Data Association,</para>
<para style="bullet" bulletText="l" spaceAfter="0">Change the new Data Association  to retrieve the correct data
and target it to the correct chart attribute</para>

<spacer length="12"/>
<para spaceAfter="0"><b>Removing an existing column and data association</b></para>

<para>
If you no longer need to use something stored in the database (or
being returned by a stored procedure), you need to
</para>
<para style="bullet" bulletText="l" spaceAfter="0">Edit the SQL to remove the item you no longer require, </para>
<para style="bullet" bulletText="l" spaceAfter="0">Change the Data Association</para>
<para style="bullet" bulletText="l" spaceAfter="0">Either make sure the target has something sensible in it or remove it altogether</para>

<para>
To edit the SQL, double-click on the line
'<font face="Courier">dataSource  = ODBCDataSource(DataSource)</font>'
in the attributes window, then double-click on the line that begins with
'<font face="Courier">sql = </font>'. You can then remove the name of
the item you no longer need. This will no longer be retrieved from the
data base.
</para>

<para>
To edit the data associations, find the line in the source window that
refers to the item you want to remove, right click on it and click on
the button labelled 'Remove'. This data association then disappears completely.
You will notice that in the attributes window, it changes to something like this:
</para>

<para><font face="Courier">
element04 = DataAssociation(column=0, target=None, assocType='vector')
</font></para>

<para>
If no other data associations below it are actually being used, you
can change the size attribute to remove them as well.
</para>

<para>
To do this, go back to the top level (so the header
of the Attributes window says 'self.Attr'), then double-click on
the line that says something like
'<font face="Courier">associations  = Array(3, DataAssociation)</font>'
, click on the line that says '<font face="Courier">size ='</font> and edit the number.
</para>

<para>
A simpler, 'quick and dirty' way of doing this is to edit the Data
Association so that the target reads 'None'. The data is still
retrieved from the database, but is not used. This is only suitable if
you don't want something to appear in your chart any longer but the
structure of the data in the database will not change.
</para>

<para>
If you are removing the data association because you want that element
to be static (for example, a title which will now be the same on every
chart rather than being data aware), you should edit it in the
attributes window so that it contains what you want. If you want to
remove it completely, find any lines referring to it in the source
window, right click on them and click on the 'Remove' button. Once all
the lines that refer to it have been removed, you can remove the line that
added it to your chart in the first place (the one that begins with
'<font face="Courier">self._add(self, '</font> and then the name of
that element and its attributes).
</para>


<condPageBreak height="60"/>
<spacer length="12"/>
<para spaceAfter="0"><b>Changing an existing column and data association in place</b></para>

<para>
Usually this will consist of either adding or removing data
associations. If you use the column names (rather than a '*') in the
SQL, changing the order of the columns in the database should not
break anything.
</para>

<nextFrame/>

<outlineAdd level="2">Data Association Types</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/> Data Association Types</b>
</para>

<para>
This section gives a more formalized explanation of how Data
Associations work, with more varied examples. We covered how most of
them work in the various worked examples and the previous section. You
can skip this section unless you need it.
</para>

<para>
Assume we have a bunch of columns:
</para>

<!--
<codesnippet language="python">
1   a01 a02 a03 a04
1   a11 a12 a13 a14
1   a21 a12 a13 a24
1   a11 a12 a13 a34
2   b01 b02 b03 b04
2   b11 b12 b13 b14
2   b21 b12 b13 b24
2   b11 b12 b13 b34
3   c01 c02 c03 c04
3   c11 c12 c13 c14
3   c21 c12 c13 c24
3   c11 c12 c13 c34
</codesnippet>-->

<blockTable style="DatabaseContinuationStyle">
<tr><td>1</td><td>a01</td><td>a02</td><td>a03</td><td>a04</td></tr>
<tr><td>1</td><td>a11</td><td>a12</td><td>a13</td><td>a14</td></tr>
<tr><td>1</td><td>a21</td><td>a12</td><td>a13</td><td>a24</td></tr>
<tr><td>1</td><td>a11</td><td>a12</td><td>a13</td><td>a34</td></tr>
<tr><td>2</td><td>b01</td><td>b02</td><td>b03</td><td>b04</td></tr>
<tr><td>2</td><td>b11</td><td>b12</td><td>b13</td><td>b14</td></tr>
<tr><td>2</td><td>b21</td><td>b12</td><td>b13</td><td>b24</td></tr>
<tr><td>2</td><td>b11</td><td>b12</td><td>b13</td><td>b34</td></tr>
<tr><td>3</td><td>c01</td><td>c02</td><td>c03</td><td>c04</td></tr>
<tr><td>3</td><td>c11</td><td>c12</td><td>c13</td><td>c14</td></tr>
<tr><td>3</td><td>c21</td><td>c12</td><td>c13</td><td>c24</td></tr>
<tr><td>3</td><td>c11</td><td>c12</td><td>c13</td><td>c34</td></tr>
<tr><td>3</td><td>c11</td><td>c12</td><td>c13</td><td>c34</td></tr>
</blockTable>

<spacer length="12"/>

<outlineAdd level="3">scalar</outlineAdd>
<para style="h3">
<b>scalar:</b>
</para>
<para>
the column specification must be a scalar. The associated target
is set to the value of that column in the first row of the data block.
Typically the chartId is a scalar, it normally has a data association
like
</para>
<codesnippet language="python">
    DataAssociation(column=0, target='chartId', assocType='scalar')
</codesnippet>
<para>
Assuming that the grouping column is the default=1 then the row grouping
will mean that chartId will receive the values i1, i2 and i2 with each data
block. Note that although we see more than one value in column 0 corresponding
to the rows i1 only the first of such rows is used for a scalar. So another
scalar defined by
</para>
<codesnippet language="python">
    DataAssociation(column=1, target='bongo', assocType='scalar')
</codesnippet>
<para>
would mean that self.bongo received the values a01, b01 and c01.
</para>

<spacer length="12"/>
<outlineAdd level="3">vector</outlineAdd>
<para style="h3">
<b>vector:</b>
</para>
<para>
the column specification can be a scalar or a sequence.
With a scalar the target receives a row vector corresponding
to the selected column i.e. all the rows in the group. When a
list is used the elements of the output vector become lists
themselves.
</para>

<codesnippet language="python">
    SELECT Id, C1, C2 FROM example
    column=0, target='chartId', assocType='scalar'
    column=1, target='data', assocType='vector'
    chartId:1
        data:['a01', 'a11', 'a21', 'a11']

    chartId:2
        data:['b01', 'b11', 'b21', 'b11']

    chartId:3
        data:['c01', 'c11', 'c21', 'c11']

    SELECT Id, C1, C2 FROM example
    column=0, target='chartId', assocType='scalar'
    column=[1, 2], target='data', assocType='vector'
    chartId:1
        data:[('a01', 'a02'), ('a11', 'a12'), ('a21', 'a12'), ('a11', 'a12')]

    chartId:2
        data:[('b01', 'b02'), ('b11', 'b12'), ('b21', 'b12'), ('b11', 'b12')]

    chartId:3
        data:[('c01', 'c02'), ('c11', 'c12'), ('c21', 'c12'), ('c11', 'c12')]
</codesnippet>

<spacer length="12"/>
<outlineAdd level="3">matrix</outlineAdd>
<para style="h3">
<b>matrix:</b>
</para>

<para>
the column specification can be a scalar, a list or a list of lists. A scalar
is treated as a single element list.
</para>
<para>
as an example:</para>
<codesnippet language="python">
SELECT Id, C1, C2, C3  FROM example
column=0, target='chartId', assocType='scalar'
column=1, target='cat', assocType='matrix'
column=[2, 3], target='dog', assocType='matrix'
column=[[1, 2], [2, 3]], target='data', assocType='matrix'
chartId:1
cat:(('a01',), ('a11',), ('a21',), ('a11',))
dog:(('a02', 'a03'), ('a12', 'a13'), ('a12', 'a13'), ('a12', 'a13'))
data:((('a01', 'a02'), ('a02', 'a03')),
 (('a11', 'a12'), ('a12', 'a13')),
 (('a21', 'a12'), ('a12', 'a13')),
 (('a11', 'a12'), ('a12', 'a13')))

chartId:2
cat:(('b01',), ('b11',), ('b21',), ('b11',))
dog:(('b02', 'b03'), ('b12', 'b13'), ('b12', 'b13'), ('b12', 'b13'))
data:((('b01', 'b02'), ('b02', 'b03')),
 (('b11', 'b12'), ('b12', 'b13')),
 (('b21', 'b12'), ('b12', 'b13')),
 (('b11', 'b12'), ('b12', 'b13')))

chartId:3
cat:(('c01',), ('c11',), ('c21',), ('c11',))
dog:(('c02', 'c03'), ('c12', 'c13'), ('c12', 'c13'), ('c12', 'c13'))
data:((('c01', 'c02'), ('c02', 'c03')),
 (('c11', 'c12'), ('c12', 'c13')),
 (('c21', 'c12'), ('c12', 'c13')),
 (('c11', 'c12'), ('c12', 'c13')))
</codesnippet>

<spacer length="12"/>
<outlineAdd level="3">tmatrix</outlineAdd>
<para style="h3">
<b>tmatrix:</b>
</para>

<para>
the column specification can be a scalar, a list or a list of lists. A scalar
is treated as a single element list.
</para>
<para>
When the column spec is a simple list as in HorizontalBarChart we get
</para>
<codesnippet language="python">
    SELECT Id, C1, C2, C3, C4 FROM example
    column=0, target='chartId', assocType='scalar'
    column=1, target='cat', assocType='vector'
    column=[2], target='data', assocType='tmatrix'
    column=4, target='label', assocType='vector'
    chartId:1
        cat:['a01', 'a11', 'a21', 'a11']
        data:(('a02', 'a12', 'a12', 'a12'),)
        label:['a04', 'a14', 'a24', 'a34']

    chartId:2
        cat:['b01', 'b11', 'b21', 'b11']
        data:(('b02', 'b12', 'b12', 'b12'),)
        label:['b04', 'b14', 'b24', 'b34']

    chartId:3
        cat:['c01', 'c11', 'c21', 'c11']
        data:(('c02', 'c12', 'c12', 'c12'),)
        label:['c04', 'c14', 'c24', 'c34']
</codesnippet>

<para>
As an example consider treating the above data as a time series with
dates in column 1 i.e. a01 is a date. The data are in columns 2, 3, 4
so we use pairs [1,2], [1,3] and [1,4], this is used in linechart.py.
For a single chart we should have a list of lists of pairs.
</para>

<codesnippet language="python">
    SELECT Id, C1, C2, C3, C4 FROM example
    column=0, target='chartId', assocType='scalar'
    column=[[1, 2], [1, 3], [1, 4]], target='data', assocType='tmatrix'
    chartId:1
    data:
        (((a01, a02), (a11, a12), (a21, a12), (a11, a12)),
        ((a01, a03), (a11, a13), (a21, a13), (a11, a13)),
        ((a01, a04), (a11, a14), (a21, a24), (a11, a34)))

    chartId:2
    data:
        (((b01, b02), (b11, b12), (b21, b12), (b11, b12)),
        ((b01, b03), (b11, b13), (b21, b13), (b11, b13)),
        ((b01, b04), (b11, b14), (b21, b24), (b11, b34)))

    chartId:3
    data:
        (((c01, c02), (c11, c12), (c21, c12), (c11, c12)),
        ((c01, c03), (c11, c13), (c21, c13), (c11, c13)),
        ((c01, c04), (c11, c14), (c21, c24), (c11, c34)))
</codesnippet>

<spacer length="12"/>
<outlineAdd level="3">rowmap</outlineAdd>
<para style="h3">
<b>rowmap:</b>
</para>

<para>
the column specification can be a list or a list of lists.
</para>
<para>
Rowmaps are used to pick individual elements out of a row of data and
convert them into a list or list of lists.
</para>
<codesnippet language="python">
SELECT Id, C1, C2, C3, C4  FROM example
column=0, target='chartId', assocType='scalar'
column=[1, 2, 3, 4], target='cat', assocType='rowmap'
column=[1, 3], target='dog', assocType='rowmap'
column=[[2, 3], [1, 4]], target='data', assocType='rowmap'
chartId:1
cat:['a01', 'a02', 'a03', 'a04']
dog:['a01', 'a03']
data:[['a02', 'a03'], ['a01', 'a04']]

chartId:2
cat:['b01', 'b02', 'b03', 'b04']
dog:['b01', 'b03']
data:[['b02', 'b03'], ['b01', 'b04']]

chartId:3
cat:['c01', 'c02', 'c03', 'c04']
dog:['c01', 'c03']
data:[['c02', 'c03'], ['c01', 'c04']]
</codesnippet>

<para>
The following is an example of one in use, this is from the QRI chart drawing2_returns.py:
</para>
<codesnippet language="python">
dataSource.associations.element01.assocType='rowmap'
dataSource.associations.element01.column    = [4,7,10,13,16]
dataSource.associations.element01.target    = 'chart.categoryAxis.categoryNames'
</codesnippet>


<nextFrame/>


<outlineAdd level="1">New Drawing Editor Features</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="8"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
New Drawing Editor Features
</para>

<outlineAdd level="2">
Test Mode</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Test Mode</b>
</para>
<para>
This isn't actually a new feature, but it has been expanded slightly.
It is also mentioned here since it works well with the new diagnostic
features mentioned below. Setting the chart attribute 'test' to 1
will fetch the first set of data from the database in a data aware
chart. Setting it to 2 will fetch the second, and so on. This is very
useful when making sure that charts actually work.
</para>
<para>
One new feature of the test mode is that any 'test' attributes which
are set can be automatically stripped out of the chart code. If you
have a number of tests set saved in the code it can both bloat the
size of the code, and fix the results of the chart rather than having
them be dynamic. For example, if test was set to three then all charts
produced with that chart class would always be from the third set of
data pulled from the database.
</para>
<para>
To turn this on or off, select  'Filter test attr' from the Options
menu.
</para>


<spacer length="12"/>


<outlineAdd level="2">
Errors</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Errors</b>
</para>
<para>
If you have the 'log' window minimized to conserve space, even having
error messages appearing in red text won't draw them to your
attention. The Drawing Editor now pops-up a requester telling you both that you
have had an error and what it is. If you want more details on it, you
can then look in the log window.
</para>

<spacer length="6"/>
<!--full size:-->
<illustration width="189" height="119">
<image file="images/error.gif" x="0" y="0" width="189" height="119"/>
</illustration>
<spacer length="12"/>

<para>
When one of these pops-up, the Drawing Editor will also beep to get your
attention. If you are finding this annoying, you can toggle it off or
on using the 'Error bells' item in the Options menu.
</para>

<spacer length="12"/>


<outlineAdd level="2">
Diagnostics</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
Diagnostics</b>
</para>

<para>
Two new diagnostic features have been added to Guiedit: Debug_memo and
a diagnostic chart.
</para>

<spacer length="6"/>

<para spaceAfter="0"><b>Debug_Memo</b></para>
<para>
If a data aware chart is crashing midway through a chart run, we
need a way of gathering as much information as possible about the
cause. Debug_memo is a way of doing this.
</para>
<para>
To switch on DebugMemo, edit the line in the chart class (from the
source window, by right clicking on it and changing it in the Alter
Edit dialog box) that has the 'go' method. This will be the last line
in the file (or near it), and will look something like this:
</para>
<codesnippet language="python">
SampleDataChart().go()
</codesnippet>

<para>Add in 'debug=1', so it looks something like this:</para>

<codesnippet language="python">
SampleDataChart().go(debug=1)
</codesnippet>

<para>
The next time the chart has a problem, it should save a debug file.
It's file name will be in the form of 'RL_classname_pickle.dbg',
so for the above example you would have a file called
'RL_SampleDataChart_pickle.dbg'.
</para>
<para>
The following information will probably not be suitable for
users, but may be of assistance to anyone supporting the chart classes
with problems.
</para>
<para>
To see the output from a debug memo, start up Python and do the
following (where yourDebugFileName is the name of the file produced by
DebugMemo):
</para>
<codesnippet language="python">
from reportlab.lib.utils import DebugMemo
dbg = DebugMemo(fn=yourDebugFileName,mode='r')
dbg.load()
dbg.show()
</codesnippet>
<para>
This will show information including the traceback produced, the data
which produced the error, any command line arguments, the version
numbers for various files and so on.
</para>

<spacer length="6"/>

<para spaceAfter="0"><b>The Diagnostic chart</b></para>
<para>
We have produced a chart which will show a number of useful
pieces of information about your system. These include the current
working directory, any arguments used from the sql of that chart and
the path.
</para>
<para>
This chart is called <font face="Courier">diagnostic.py</font> and is located in the
<font face="Courier">rlextra\graphics\guiedit</font> directory (under your Python directory).
</para>
<para>
If you ever need to send it (either to us or whoever is providing
support for your charts), make sure you export it to a suitable format
(e.g. GIF) and send that image.
</para>

<nextFrame/>




<outlineAdd level="1">Using 'Knockout'</outlineAdd>
<para style="h1">
<name id="sectionNumber" value="9"/><seqReset id="subsectionNumber"/>
<getName id="sectionNumber"/>
Using 'Knockout'
</para>

<outlineAdd level="2">
'Knockout' - what it is, and why use it</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
'Knockout' - what it is, and why you might want to use it</b>
</para>

<para>
Simply put, 'knockout' is when a colour which overlays another colour
'knocks out' anything below it. It's the removal of colour in one area
to accommodate another colour (i.e. it's an area of a background colour
that does not print in that colour).
</para>

<para>
Using knockout adds the complication that the version of document (or
graph or diagram) that you see in guiedit will not necessarily match
the one you get when you print it out. What are the advantages?
If you are using a printer who prints the black ('key') plate last,
any black lines or grids used in construction of graphs and charts
will appear <i>over</i> the bars or lines that should be the focus of
the chart. Knockout removes any lines under the bars (or pie etc) so
that they won't 'show through'.
</para>

<para>
Note that knockout is renderer specific. The whole concept is only
useful in a renderer that supports it. Currently it is only supported
in renderPS_SEP - our Postscript renderer. This means that it isn't
possible to use knockout with bitmaps (and isn't currently supported
in PDF, though that may change in the future).
</para>

<para>
Consider the following example, which illustrates all aspects of
knockout with two squares. It uses non-spot colours with the two
colours overlapping, providing 8 combinations. This is how it would
look in Guiedit.
</para>

<spacer length="6"/>
<illustration width="235" height="130">
<pageGraphics>
<!--<catchForms storageFile="tko_samples.data"/>-->
<rect x="72" y="0" width="235" height="130" fill="no" stroke="yes"/>
<translate dx="0" dy="-70"/>
<setFont name="Times-Roman" size="10"/>
<drawCentredString x="189.5" y="55">Knockout example</drawCentredString>
<!--<doForm name="PF0"/>-->
</pageGraphics>
</illustration>
<spacer length="24"/>

<para>
Going from left to right, top to bottom, we can see that from the labelling that:
</para>

<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="0">F00 has the large square drawn first and no knockout,</para>
<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="0">F01 has the large square drawn first and the knockout on for the small square,</para>
<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="0">L00 has the small square drawn first and no knockout,</para>
<para style="bullet" bulletText="l">L01 has the small square drawn first and the knockout on for the small square,</para>
<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="-6">F10 has the large square drawn first and the knockout on for the large square,</para>
<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="-6">F11 has the large square drawn first and the knockout on for both squares, </para>
<para style="bullet" bulletText="l" spaceAfter="0" spaceBefore="-6">L10 has the small square drawn first and the knockout on for the large square, </para>
<para style="bullet" bulletText="l" spaceBefore="0" spaceAfter="12">L11 has the small square drawn first and the knockout on for both squares.</para>

<para>
Notice how in Guiedit, when the large square is drawn first, the
smaller square always appears on top of it, and when the smaller
square is drawn first the larger square always overwrites it.
</para>

<para>
The four illustrations on the next page show how it looks when split
into its constituent colour separations.
</para>

<para>
Notice how where the little square has the knockout set, it 'punches
out' a hole in anything below it. The cyan separation of the squares
labelled F01 and F11 show this quite well, where the small squares have
knocked out areas of the large squares.
</para>

<condPageBreak height="640"/>
<spacer length="6"/>
<illustration width="235" height="130">
<pageGraphics>
<rect x="72" y="0" width="235" height="130" fill="no" stroke="yes"/>
<translate dx="-115" dy="-685"/>
<!--<doForm name="PF2"/>-->
</pageGraphics>
<setFont name="Times-Roman" size="10"/>
<drawCentredString x="189.5" y="-12">Knockout example: Cyan separation</drawCentredString>
</illustration>
<spacer length="24"/>

<spacer length="6"/>
<illustration width="235" height="130">
<pageGraphics>
<rect x="72" y="0" width="235" height="130" fill="no" stroke="yes"/>
<translate dx="-115" dy="-685"/>
<!--<doForm name="PF3"/>-->
</pageGraphics>
<setFont name="Times-Roman" size="10"/>
<drawCentredString x="189.5" y="-12">Knockout example: Magenta separation</drawCentredString>
</illustration>
<spacer length="24"/>

<spacer length="6"/>
<illustration width="235" height="130">
<pageGraphics>
<rect x="72" y="0" width="235" height="130" fill="no" stroke="yes"/>
<translate dx="-115" dy="-685"/>
<!--<doForm name="PF4"/>-->
</pageGraphics>
<setFont name="Times-Roman" size="10"/>
<drawCentredString x="189.5" y="-12">Knockout example: Yellow separation</drawCentredString>
</illustration>
<spacer length="24"/>

<spacer length="6"/>
<illustration width="235" height="130">
<pageGraphics>
<rect x="72" y="0" width="235" height="130" fill="no" stroke="yes"/>
<translate dx="-115" dy="-685"/>
<!--<doForm name="PF5"/>-->
</pageGraphics>
<setFont name="Times-Roman" size="10"/>
<drawCentredString x="189.5" y="-12">Knockout example: Black ('Key') separation</drawCentredString>
</illustration>
<spacer length="24"/>
<nextFrame/>

<para>
L01 and L11 also have the knockout set on the small squares, but
nothing is punched out of the large square for these. This is because
our implementation of knockout is dependant on the <i>ordering</i> of objects.
</para>
<para>
When knockout is set on an object, it will knockout anything which has
already been drawn (i.e. 'below' it in the ordering of items on the
canvas). In these L01 and L11, the large square hasn't been drawn yet
when the small one is created, so there is nothing there to knockout.
</para>
<para>
This is also illustrated by the squares labelled L10 and L11 in the
Yellow separation. Because the large square has knockout set and is
drawn second, it knocks out the smaller square - and since the smaller
square is smaller, it is removed completely.
</para>

<outlineAdd level="2">
How to use knockout</outlineAdd>
<para style="h2">
<b><getName id="sectionNumber"/>.<seq id="subsectionNumber"/>
How to use knockout</b>
</para>

<para>
OK, so now we know what knockout is, how do we actually use it?
</para>

<para>
We saw about the <i>spotName</i> and <i>density</i> attributes for
colours (CMYK and PCMYK colors) in section 4.2 ("Working with
Colours"). There is another optional attribute called 'knockout'.
This parameter is optional, if it isn't specified it defaults to None.
None in this case means 'use the default' (see below).
</para>

<para>
This means that knockout is an attribute of a <i>colour</i> rather than
a shape or object. If knockout is set to 1, then all objects using
that colour will knockout anything underneath them in the way we've
already seen.
</para>

<para>
As an example, this is how the colour used for the big squares in the example is defined:
</para>

<para style="code_snippet">
PCMYKColor(100,100,0,0,density=80,knockout=0)
</para>

<para>
The default is to have knockout set to 1 - so everything 'knocks out'.
This can be changed by adding a line to the file rl_config.py. If you add the line :
</para>

<para style="code_snippet">
knockout =                  0
</para>

<para>
to the rl_config file, knockout will be turned off (and 'knockout = 1'
turns it back on again). Omitting it altogether also turns it back on
by reverting to the default.
</para>


</story>
</document>
