Source for file SvgGrapher.php

Documentation is available at SvgGrapher.php

  1. <?php
  2. /**
  3.  * $Source: /cvsroot/svggrapher/svggrapher/SvgGrapher.php,v $
  4.  *
  5.  * 
  6.  *
  7.  * @version $Id: SvgGrapher.php,v 1.20 2007/10/23 09:22:51 geelweb Exp $
  8.  * @author Guillaume L. <guillaume@geelweb.org>
  9.  * @copyright Copyright © 2006, Guillaume Luchet.
  10.  * @license http://opensource.org/licenses/bsd-license.php BSD License
  11.  * @package SvgGrapher
  12.  */
  13.  
  14. /**
  15.  * Define the library base path.
  16.  * Be carefull if you redefine this!
  17.  * @var string 
  18.  */
  19. if(!defined('SVGGRAPHER_CLASS_PATH')) {
  20.     define('SVGGRAPHER_CLASS_PATH'dirname(__FILE__));
  21. }
  22.  
  23. // dependances {{{
  24.  
  25. /**
  26.  * Include the library config file
  27.  */
  28. require_once SVGGRAPHER_CLASS_PATH '/SvgGrapher.config.php';
  29.  
  30. /**#@+
  31.  * Include the objects helper
  32.  */
  33. require_once SVGGRAPHER_CLASS_PATH '/mains/PluginManager.php';
  34. require_once SVGGRAPHER_CLASS_PATH '/mains/Box.php';
  35. require_once SVGGRAPHER_CLASS_PATH '/mains/Curve.php';
  36. require_once SVGGRAPHER_CLASS_PATH '/mains/SvgDocumentRenderer.php';
  37. require_once SVGGRAPHER_CLASS_PATH '/XMLDocument.php';
  38. /**#@-*/
  39.  
  40. /**#@+
  41.  * Include the mains svg elements objects
  42.  */
  43. require_once SVGGRAPHER_ELEMENTS_PATH '/GElement.php';
  44. require_once SVGGRAPHER_ELEMENTS_PATH '/DefsElement.php';
  45. require_once SVGGRAPHER_ELEMENTS_PATH '/LineElement.php';
  46. /**#@-*/
  47.  
  48. // }}}
  49. // doc {{{
  50.  
  51. /**
  52.  * SvgGrapher.
  53.  *
  54.  * Build a svg document.
  55.  *
  56.  * The most of plugin functionality are plugin defined. The plugin types are :
  57.  * - <b>dataprovider</b> for get the datas from various sources.
  58.  * - <b>defs</b> for the various svg definition.
  59.  * - <b>filter</b> for the curves filters.
  60.  * - <b>internal</b> for the internal functions (must already be in the internal
  61.  * directory).
  62.  * - <b>marker</b> for the curves makers
  63.  * - <b>script</b> for the svg scripts.
  64.  * - <b>visual</b> for the visual representation of the curves.
  65.  * 
  66.  * For each plugin the file must be named <b>svgGrapher.type.keyword.php</b> and
  67.  * must contain a function named <b>svgGrapher_type_keyword</b>. eg: to the
  68.  * visual plugin who defined the line representation of curve the file name is
  69.  * <i>svgGrapher.visual.line.php</i> and the function is named
  70.  * <i>svgGrapher_visual_line</i>.
  71.  *
  72.  * All plugins are call using the PluginManager class, the plugins can
  73.  * access to the SvgGrapher class using the SvgGrapher::singleton() method.
  74.  *
  75.  * The plugins paths are define in the PluginManager class file.
  76.  *
  77.  * You can redefine most of constant using by the library, they are listed in
  78.  * the <i>SvgGrapher.constants.php</i>, you must redefined them before include
  79.  * SvgGrapher.php
  80.  *
  81.  * @author Guillaume L. <guillaume@geelweb.org>
  82.  * @link http://www.geelweb.org
  83.  * @license http://opensource.org/licenses/bsd-license.php BSD License
  84.  * @copyright Copyright © 2006, Guillaume Luchet.
  85.  * @version CVS: $Id: SvgGrapher.php,v 1.20 2007/10/23 09:22:51 geelweb Exp $
  86.  * @package SvgGrapher
  87.  * @tutorial SvgGrapher.pkg
  88.  */ // }}}
  89. class SvgGrapher 
  90. {
  91.     // properties {{{
  92.  
  93.     /**
  94.      * Instance (singleton) of the class
  95.      * @var SvgGrapher 
  96.      */
  97.     static $instance false;
  98.  
  99.     /**
  100.      * svgDom
  101.      * 
  102.      * @var mixed 
  103.      * @access public
  104.      */
  105.     public $svgDom;
  106.     // svg elements {{{
  107.  
  108.     /**
  109.      * Main svg document
  110.      * @var SvgElement 
  111.      */
  112.     public $svgDocument = NULL;
  113.  
  114.     /**
  115.      * Titles of the svg document
  116.      * @var GElement 
  117.      */
  118.     public $svgTitles = NULL;
  119.  
  120.     /**
  121.      * Document's legend
  122.      * @var GElement 
  123.      */
  124.     public $svgLegend = NULL;
  125.  
  126.     /**
  127.      * Defs elements of the svg document
  128.      * @var DefsElement 
  129.      */
  130.     public $svgDefs = NULL;
  131.  
  132.     /**
  133.      * CDATA section of the svg document
  134.      * @var FragmentElement 
  135.      */
  136.     public $svgEcma = NULL;
  137.  
  138.     /**
  139.      * Graph section of the svg document
  140.      * @var GElement 
  141.      */
  142.     public $svgGraphPane = NULL;
  143.  
  144.     /**
  145.      * Group element to curve tooltips
  146.      * @var GElement 
  147.      */
  148.     public $svgToolTips = NULL;
  149.  
  150.     // }}}
  151.     // boxes {{{
  152.  
  153.     /**
  154.      * boxDoc
  155.      *
  156.      * @var Box 
  157.      * @access public
  158.      */
  159.     public $boxDoc;
  160.  
  161.     /**
  162.      * boxTitle
  163.      * 
  164.      * @var Box 
  165.      * @access public
  166.      */
  167.     public $boxTitle;
  168.     
  169.     /**
  170.      * boxTagsX
  171.      * 
  172.      * @var Box 
  173.      * @access public
  174.      */
  175.     public $boxTagsX;
  176.     
  177.     /**
  178.      * boxTagsY
  179.      * 
  180.      * @var Box 
  181.      * @access public
  182.      */
  183.     public $boxTagsY;
  184.     
  185.     /**
  186.      * boxLabelX
  187.      * 
  188.      * @var Box 
  189.      * @access public
  190.      */
  191.     public $boxLabelX;
  192.     
  193.     /**
  194.      * boxLabelY
  195.      * 
  196.      * @var Box 
  197.      * @access public
  198.      */
  199.     public $boxLabelY;
  200.  
  201.     /**
  202.      * boxGraphPane
  203.      * 
  204.      * @var Box 
  205.      * @access public
  206.      */
  207.     public $boxGraphPane;
  208.  
  209.     /**
  210.      * boxLegend
  211.      * 
  212.      * @var Box 
  213.      * @access public
  214.      */
  215.     public $boxLegend;
  216.  
  217.     // }}}
  218.  
  219.     /**
  220.      * Detailled curves datas
  221.      * @var Curve array
  222.      */
  223.     public $curves = array();
  224.  
  225.     /**
  226.      * Abscisse indications.
  227.      * var array
  228.      */
  229.     public $tagsX = array();
  230.  
  231.     /**
  232.      * tagsY
  233.      * 
  234.      * @var array 
  235.      * @access public
  236.      */
  237.     public $tagsY = array();
  238.  
  239.     /**
  240.      * Round level.
  241.      * @var integer 
  242.      */
  243.     public $resolution = RESOLUTION_ENDING_ONE_ZERO;
  244.  
  245.     /**
  246.      * Number of decimals.
  247.      * @var integer 
  248.      */
  249.     public $decimal = DECIMAL_NUMBER;
  250.     
  251.     /**
  252.      * Screen resolution.
  253.      * @var integer 
  254.      */
  255.     public $dpiResolution = DEFAULT_DPI_RESOLUTION;
  256.  
  257.     /**
  258.      * Space between graph and abscisse tags.
  259.      * default: 5% of the width, limit to 15.
  260.      * @var float 
  261.      */
  262.     public $nicerLookXOffset = NICER_LOOK_X_OFFSET;
  263.  
  264.     /**
  265.      * Space between graph and ordinate tags.
  266.      * default: 5% of the width, limit to 15.
  267.      * @var float 
  268.      */
  269.     public $nicerLookYOffset = NICER_LOOK_Y_OFFSET;
  270.  
  271.     /**
  272.      * Number of pixel between each line of the abscisse grid.
  273.      * @var integer 
  274.      */
  275.     public $gridLineXDelta = GRID_LINES_X_DELTA;
  276.     
  277.     /**
  278.      * Number of pixel between each line of the ordinate grid.
  279.      * @var integer 
  280.      */
  281.     public $gridLineYDelta = GRID_LINES_Y_DELTA;
  282.     
  283.     /**
  284.      * Padding of the first point from the abscisse.
  285.      * @var float 
  286.      */
  287.     public $plotOffsetX = PLOT_OFFSET_X;
  288.     
  289.     /**
  290.      * Padding of the first point from the ordinate.
  291.      * @var float 
  292.      */
  293.     public $plotOffsetY = PLOT_OFFSET_Y;
  294.  
  295.     /**
  296.      * Min value to calculate the scale.
  297.      *
  298.      * This value is not calculated, you must fixe
  299.      * it if the min value is not the "real" min value passed in the curve data.
  300.      *
  301.      * @var integer 
  302.      */
  303.     public $min = 0;
  304.  
  305.     /**
  306.      * Max value to calculate the scale.
  307.      *
  308.      * This value is not calculated, you must fixe it if the max value is not
  309.      * the "real" max value passed in the curve data.
  310.      *
  311.      * @var integer 
  312.      */
  313.     public $max = 0;
  314.        
  315.     /**
  316.      * Coefficient pixel/data to the ordinate axe.
  317.      * @var float 
  318.      */
  319.     public $factorY = 0;
  320.     
  321.     /**
  322.      * Label X value.
  323.      * @var string 
  324.      */
  325.     public $labelX = DEFAULT_LABEL_X;
  326.  
  327.     /**
  328.      * Y label value.
  329.      * @var string 
  330.      */
  331.     public $labelY = DEFAULT_LABEL_Y;
  332.  
  333.     /**
  334.      * Graph title.
  335.      * @var string 
  336.      */
  337.     public $title = DEFAULT_TITLE
  338.  
  339.     /**
  340.      * minorStepYDelta
  341.      * 
  342.      * @var mixed 
  343.      * @access public
  344.      */
  345.     public $minorStepYDelta = MINOR_STEP_Y_DELTA;
  346.  
  347.     /**
  348.      * Rotation angle (degree) for the abscisse tags
  349.      * @var integer 
  350.      */
  351.     public $tagXRotation = -30;
  352.  
  353.     /**
  354.      * Number of lines to the abscisses grid
  355.      * @var int 
  356.      */
  357.     public $gridLineX = 0;
  358.  
  359.     /**
  360.      * Frequency of the abscisses tags
  361.      */
  362.     public $tagXGapFrequency = 1;
  363.  
  364.     /**
  365.      * Y label rotation
  366.      * @var int 
  367.      */
  368.     public $labelYRotation = -90;
  369.  
  370.     /**
  371.      * Y minor step
  372.      * @var integer 
  373.      */
  374.     public $minorStepY = 8;
  375.  
  376.     /**
  377.      * Rotation of the Y tags
  378.      * @var integer 
  379.      */
  380.     public $tagYRotation = 0;
  381.  
  382.     /**
  383.      * Number  of line to the grid of the Y axe
  384.      * @var int 
  385.      */
  386.     public $gridLineY = GRID_LINES_Y;
  387.  
  388.     /**
  389.      * display
  390.      *
  391.      * You can't access directly this variable using
  392.      * <code>$object->display['box'] = false;</code>
  393.      * see SvgGrapher::setDisplay() for more details.
  394.      * 
  395.      * @var array 
  396.      * @access protected
  397.      */
  398.     protected $display = array(
  399.         'box'        => true,
  400.         'tagsX'      => true,
  401.         'tagsY'      => true,
  402.         'stepX'      => true,
  403.         'stepY'      => true,
  404.         'minorStepY' => true,
  405.         'legend'     => true,
  406.         'labelX'     => true,
  407.         'labelY'     => true,
  408.         'title'      => true,
  409.         'gridX'      => true,
  410.         'gridY'      => true,
  411.         'limits'     => true,
  412.         'w3link'     => true);
  413.  
  414.     /**
  415.      * limitsLines
  416.      * 
  417.      * @var array 
  418.      * @access public
  419.      */
  420.     public $limitsLines = array(
  421.         'low'    => array('value' => 0'color'=>'#FF0000'),
  422.         'median' => array('value' => 0'color'=>'#00FF00'),
  423.         'high'   => array('value' => 0'color'=>'#FF0000'),
  424.     );
  425.  
  426.     /**
  427.      * Limits of the data. (calculed with the internal findrange plugin)
  428.      * @var array 
  429.      */
  430.     public $range = array('min' => 0'max' => 0'delta' => 0);
  431.  
  432.     /**
  433.      * _needUpdate
  434.      *
  435.      * true if boxes position and scale need to be recalulated
  436.      *
  437.      * @var bool 
  438.      * @access private
  439.      */
  440.     private $_needUpdate = true;
  441.  
  442.     /**
  443.      * boxesPositions
  444.      *
  445.      * Boxes positions array, acceptables values are:
  446.      * - title : top or bottom
  447.      * - legend : left or right
  448.      *
  449.      * @var array 
  450.      * @access public
  451.      */
  452.     public $boxesPositions = array(
  453.         'title' => 'top',
  454.         'legend' => 'right');
  455.  
  456.     /**
  457.      * rendererCallBacks
  458.      *
  459.      * Call back functions used in SvgDocumentRenderer to do operations on tags.
  460.      * 
  461.      * @var array 
  462.      * @access public
  463.      */
  464.     public $rendererCallBacks = array(
  465.         'tagsX' => NULL,
  466.         'tagsY' => NULL);
  467.  
  468.     // }}}
  469.     // SvgGrapher::__construct() {{{
  470.  
  471.     /**
  472.      * Constructor.
  473.      *
  474.      * @param float $width width width
  475.      * @param float $height document height
  476.      * @param bool $setEHOn true to set exception handler on
  477.      * @return void 
  478.      */
  479.     public function __construct($width=400$height=300$setEHOn=false
  480.     {
  481.         if(!self::$instance{
  482.             self::$instance $this;
  483.         }
  484.         if($setEHOn{
  485.             set_exception_handler(array('SvgGrapher''exceptionHandler'));
  486.         }
  487.         $this->_importCoreFunctions();
  488.         // init boxes
  489.         $this->boxDoc = new Box(array('width'=>$width'height'=>$height));
  490.         $this->boxGraphPane = new Box();
  491.         $this->boxTitle = new Box();
  492.         $this->boxLegend = new Box();
  493.         $this->boxLabelX = new Box();
  494.         $this->boxLabelY = new Box();
  495.         $this->boxTagsX = new Box();
  496.         $this->boxTagsY = new Box();
  497.         // init svgElements
  498.         $this->svgDom = new XMLDocument('1.0''iso-8859-1');
  499.         $this->svgDom->createDocumentType(
  500.             'svg''-//W3C//DTD SVG 1.1//EN',
  501.             'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd');
  502.         $this->svgDocument = $this->svgDom->createRootelement('svg');
  503.         $this->svgDocument->setAttribute('xmlns''http://www.w3.org/2000/svg');
  504.         $this->svgDocument->setAttribute('xmlns:xlink''http://www.w3.org/1999/xlink');
  505.         $this->svgDocument->setAttribute('version''1.1');
  506.         $this->svgDocument->setAttribute('width'$this->boxDoc->width);
  507.         $this->svgDocument->setAttribute('height'$this->boxDoc->height);
  508.  
  509.         $this->svgGraphPane = new GElement(array('id'=>'graphPane'));
  510.         $this->svgTitles = new GElement();
  511.         $this->svgLegend = new GElement(array('id'=>'legend'));
  512.         $this->svgDefs = new DefsElement();
  513.         $this->svgEcma = array();
  514.         $this->svgToolTips = new GElement();
  515.     }
  516.  
  517.     // }}}
  518.     // SvgGrapher::singleton() {{{
  519.     
  520.     /**
  521.      * Get the current instance (singleton) of the class, or make a new
  522.      * instance.
  523.      *
  524.      * @param float $width document width (only for new instance)
  525.      * @param float $height document height (only for new instance)
  526.      * @return SvgGrapher 
  527.      */
  528.     static function singleton($width=0$height=0
  529.     {
  530.         if(!self::$instance{
  531.             self::$instance new SvgGrapher($width$height);
  532.         }
  533.         return self::$instance;
  534.     }
  535.  
  536.     // }}}
  537.     // svgGrapher::exceptionHandler() {{{
  538.  
  539.     /**
  540.      * Exception handler.
  541.      *
  542.      * @param object $exception objet Exception
  543.      * @return void 
  544.      */
  545.     static function exceptionHandler($exception
  546.     {
  547.         echo 'SvgGrapher error : ' $exception->getMessage();
  548.         exit($exception->getCode());
  549.     
  550.  
  551.     // }}}
  552.     // SvgGrapher::__set() {{{
  553.  
  554.     /**
  555.      * __set
  556.      * 
  557.      * @param mixed $property 
  558.      * @param mixed $value 
  559.      * @access public
  560.      * @return void 
  561.      */
  562.     public function __set($property$value
  563.     {
  564.         $method 'set' $property;
  565.         if(method_exists($this$method)) {
  566.             return $this->$method($value);
  567.         }
  568.         return $this->$property $value;
  569.     }
  570.  
  571.     // }}}
  572.     // SvgGrapher::__get() {{{
  573.  
  574.     /**
  575.      * __get
  576.      * 
  577.      * @param mixed $property 
  578.      * @access public
  579.      * @return void 
  580.      */
  581.     public function __get($property
  582.     {
  583.         $method 'get' $property;
  584.         if(method_exists($this$method)) {
  585.             return $this->$method();
  586.         }
  587.         return $this->$property;
  588.     }
  589.  
  590.     // }}}
  591.     // SvgGrapher::_importCoreFunctions() {{{
  592.     
  593.     /**
  594.      * Import the core functions founded in internal directory.
  595.      *
  596.      * @return boolean 
  597.      */
  598.     private function _importCoreFunctions(
  599.     {
  600.         $corePath SVGGRAPHER_CLASS_PATH '/internal/';
  601.         $coreName 'svgGrapher.internal.';
  602.         $coreDir dir($corePath);
  603.  
  604.         while(false !== ($f $coreDir->read()) ) {
  605.             if(stristr($f$coreName)) {
  606.                 include_once $corePath $f;
  607.             }
  608.         }
  609.  
  610.         $coreDir->close();
  611.         return true;
  612.     }
  613.     
  614.     // }}}
  615.     // SvgGrapher::_calculateBoxProperties() {{{
  616.     
  617.     /**
  618.      * _calculateBoxProperties
  619.      *
  620.      * boxes positions:
  621.      * - title on the document's top
  622.      * - legend on the document's right and on the title's bottom
  623.      * - graph pane under the title on the legend's left
  624.      * - X tags on the left of the graph pane
  625.      * - Y tags on the bottom of the graph pane
  626.      * - X label on the left of the X tags
  627.      * - Y label on the bottom of the X tags
  628.      * 
  629.      * @access public
  630.      * @return void 
  631.      */
  632.     private function _calculateBoxProperties(
  633.     {
  634.         if(!$this->_needUpdate{
  635.             return true;
  636.         }
  637.         // calculate the nicer look offsets
  638.         if($this->nicerLookXOffset <= 0{
  639.             $offsetX $this->boxDoc->width * 100;
  640.             $this->nicerLookXOffset = ($offsetX 15$offsetX 15;
  641.         }
  642.         if($this->nicerLookYOffset <= 0{
  643.             $offsetY $this->boxDoc->height * 100;
  644.             $this->nicerLookYOffset = ($offsetY 15$offsetY 15;
  645.         }        
  646.         
  647.         // Calculate the data scale to display in the Y axe.
  648.         $values array();
  649.         if(!empty($this->curves)) {
  650.             foreach($this->curves as $curve{
  651.                 $values array_merge($values$curve->values);
  652.             }
  653.             $this->range = svgGrapher_internal_findRange($values$this->min$this->max$this->resolution);
  654.             if ($this->range['delta'== 0{
  655.                 throw new Exception('No range to plot. Check data');
  656.                 exit(-1);
  657.             }
  658.  
  659.             // Number of lines on the X axe
  660.             $this->gridLineX = sizeof($this->tagsX);
  661.         
  662.             // Build the Y axe tags
  663.             $deltaTagsY $this->range['delta'($this->gridLineY - ($this->plotOffsetY));
  664.             for ($i 0$i $this->gridLineY$i++{
  665.                 $text $this->range['min'$deltaTagsY ($i +  $this->plotOffsetY);
  666.                 $this->tagsY[$inumber_format($text$this->decimalDECIMAL_SEPARATORTHOUSANDS_SEPERATOR);
  667.             }
  668.             $this->tagsY = array_reverse($this->tagsY);
  669.         }
  670.  
  671.         // graph pane box
  672.         $this->boxGraphPane->width = $this->boxDoc->width - ($this->nicerLookXOffset << 1);
  673.         $this->boxGraphPane->height = $this->boxDoc->height - ($this->nicerLookYOffset << 1);
  674.         $this->boxGraphPane->x = $this->nicerLookXOffset;
  675.         $this->boxGraphPane->y = $this->nicerLookYOffset;
  676.  
  677.         // calculate the properties of the title box
  678.         if($this->display['title']{
  679.             $h svgGrapher_internal_fontSizeEquiv(TITLE_STYLE$this->nicerLookYOffset;
  680.             $this->boxTitle->height = $h;
  681.             $this->boxTitle->width = $this->boxDoc->width;
  682.             $this->boxTitle->padding = array(
  683.                 'left' => $this->boxTitle->width >> 1,
  684.                 'top'  => $this->boxTitle->height >> 2);
  685.             if($this->boxesPositions['title'== 'top'{
  686.                 $this->boxTitle->x = 0;
  687.                 $this->boxTitle->y = 0;
  688.                 // update graph pane box
  689.                 $this->boxGraphPane->y += $h
  690.             elseif($this->boxesPositions['title'== 'bottom'{
  691.                 $this->boxTitle->x = 0;
  692.                 $this->boxTitle->y = $this->boxDoc->height - $h;
  693.             }
  694.             // update graph pane box
  695.             $this->boxGraphPane->height -= $h
  696.         }
  697.  
  698.         // Calculate the properties of the legend box
  699.         if($this->display['legend']{
  700.             $legends array();
  701.             foreach($this->curves as $curve{
  702.                 if(is_array($curve->legend)) {
  703.                     $legends array_merge($legends$curve->legend);
  704.                 else {
  705.                     $legends[$curve->legend;
  706.                 }
  707.             }
  708.             $longestLegendStr svgGrapher_internal_longestTag($legends);
  709.             $box svgGrapher_internal_getComputedTextLength($longestLegendStrLEGEND_TEXT_STYLE);
  710.             $this->legendTextHeight $box['height'];
  711.             
  712.             $w $box['width'($this->nicerLookYOffset << 2);
  713.             $this->boxLegend->width = $w;
  714.             $this->boxLegend->height = $this->boxGraphPane->height;
  715.             $this->boxLegend->y = $this->boxGraphPane->y
  716.             if($this->boxesPositions['legend'== 'right'{
  717.                 $this->boxLegend->x = $this->boxDoc->width - $w;
  718.             elseif($this->boxesPositions['legend'== 'left'{
  719.                 $this->boxLegend->x = $this->boxGraphPane->x;
  720.                 // update graph pane box
  721.                 $this->boxGraphPane->x += $w;
  722.             }
  723.             // update graph pane box
  724.             $this->boxGraphPane->width -= $w;
  725.         }
  726.  
  727.         // calculate the properties of the label y box
  728.         if($this->display['labelY']{
  729.             $w svgGrapher_internal_fontSizeEquiv(LABEL_Y_STYLE$this->nicerLookXOffset;
  730.             $this->boxLabelY->width = $w;
  731.             $this->boxLabelY->height = $this->boxGraphPane->height;
  732.             $this->boxLabelY->x = $this->boxGraphPane->x + $w $this->nicerLookXOffset;
  733.             $this->boxLabelY->y = $this->boxLabelY->height >> 1;
  734.             // update graph pane box
  735.             $this->boxGraphPane->width -= $w;
  736.             $this->boxGraphPane->x += $w;
  737.         }
  738.        
  739.         // calculate the properties of the tag y box
  740.         if($this->display['tagsY']{
  741.             $rotation sprintf('rotate(%s)'$this->tagYRotation);
  742.             $longestStr svgGrapher_internal_longestTag($this->tagsY);
  743.             $box svgGrapher_internal_getComputedTextLength(
  744.                 $longestStrTAGS_Y_STYLE$rotation);
  745.             $this->boxTagsY->width = $box['width'];
  746.             $this->boxTagsY->height = $box['height'];
  747.             $this->boxTagsY->x = $this->boxGraphPane->x;
  748.             // update graph pane box
  749.             $w $box['width'$this->nicerLookXOffset;
  750.             $this->boxGraphPane->width -= $w;
  751.             $this->boxGraphPane->x += $w;
  752.         }
  753.  
  754.         // calculate the properties of the label x box
  755.         if($this->display['labelX']{
  756.             $this->boxLabelX->width = $this->boxGraphPane->width;
  757.             $h svgGrapher_internal_fontSizeEquiv(LABEL_X_STYLE);
  758.             $this->boxLabelX->height = $h;
  759.             $this->boxLabelX->x = $this->boxDoc->width >> 1;
  760.             $this->boxLabelX->y = $this->boxGraphPane->y + $this->boxGraphPane->height;
  761.             // update graph pane box
  762.             $this->boxGraphPane->height -= $h;
  763.             $this->boxLegend->height -= $h;
  764.         }
  765.  
  766.         // calculate the properties of the tags x box
  767.         if($this->display['tagsX']{
  768.             $rotation sprintf('rotate(%s)'$this->tagXRotation);
  769.             $longestStr svgGrapher_internal_longestTag($this->tagsX);
  770.             $box svgGrapher_internal_getComputedTextLength(
  771.                 $longestStrTAGS_X_STYLE$rotation);
  772.             $h $box['height'$this->nicerLookYOffset;
  773.             $this->boxTagsX->width = $box['width'];
  774.             $this->boxTagsX->height = $h;
  775.             $this->boxTagsX->y = $this->boxGraphPane->y + $this->boxGraphPane->height - $box['height'];
  776.             // update graph pane box
  777.             $this->boxGraphPane->height -= $h;
  778.             $this->boxLegend->height -= $h;
  779.         }
  780.         
  781.         if(!empty($values)) {
  782.             // Calculate the lines offset of the grid
  783.             if($this->gridLineXDelta <= 0{
  784.                 $this->gridLineXDelta = $this->boxGraphPane->width / 
  785.                     ($this->gridLineX - ($this->plotOffsetX));
  786.             }
  787.             if($this->gridLineYDelta <= 0{
  788.                 $this->gridLineYDelta = $this->boxGraphPane->height / 
  789.                     ($this->gridLineY - ($this->plotOffsetY));
  790.             }
  791.             if($this->minorStepYDelta <= 0{
  792.                 $this->minorStepYDelta = $this->gridLineYDelta / $this->minorStepY;
  793.             }
  794.             $this->factorY = $this->boxGraphPane->height / $this->range['delta'];
  795.         }
  796.  
  797.         $this->_needUpdate = false;
  798.     }
  799.     
  800.     // }}}
  801.     // SvgGrapher::addCurve() {{{
  802.     
  803.     /**
  804.      * Add a curve to the graph.
  805.      *
  806.      * @param mixed $name Curve identifier.
  807.      * @param array $params params to Curve object
  808.      * @param string $color Curve color
  809.      * @return boolean 
  810.      */
  811.     
  812.     public function addCurve($name$params=array()) 
  813.     {
  814.         $curve new Curve($params$name);
  815.         $this->curves[$name$curve
  816.  
  817.         if(!sizeof($this->tagsX)) {
  818.             $this->tagsX = $params['labels'];
  819.         elseif(isset($params['labels']&& is_array($params['labels'])) {
  820.             // On rassemble les deux tableaux de label en un seul et on dedoublonne.
  821.             // Essaye de conserver l'ordre naturel des donnees.
  822.             $tmpArr array();
  823.  
  824.             foreach($this->tagsX as $idx => $tag{
  825.                 // Le label d'index courant est unique, on prend...
  826.                 if(isset($params['labels'][$idx]&& !in_array($params['labels'][$idx]$this->tagsX)) {
  827.                     $tmpArr[$params['labels'][$idx];
  828.                 }
  829.                 // La tag en cours est unique ou n'a pas deja etait pris...
  830.                 if(!(in_array($tag$params['labels']&& in_array($tag$tmpArr))) {
  831.                     $tmpArr[$tag;
  832.                 }
  833.             }
  834.             $this->tagsX = $tmpArr;
  835.         }
  836.         $this->_needUpdate = true;
  837.     }
  838.     
  839.     // }}}
  840.     // SvgGrapher::genGraph() {{{
  841.     
  842.     /**
  843.      * Build the graph.
  844.      *
  845.      * @return void 
  846.      */
  847.     public function genGraph(
  848.     {
  849.         $this->_calculateBoxProperties();
  850.  
  851.         SvgDocumentRenderer::render();
  852.  
  853.         foreach($this->svgEcma as $js
  854.             $this->svgDocument->appendChild($js)
  855.         }
  856.         if(count($this->svgDefs->children)>0
  857.             $this->svgDocument->appendChild($this->svgDefs)
  858.         }
  859.         if(count($this->svgTitles->children)>0
  860.             $this->svgDocument->appendChild($this->svgTitles)
  861.         }
  862.         if(count($this->svgLegend->children)>0
  863.             $this->svgDocument->appendChild($this->svgLegend)
  864.         }
  865.  
  866.         $this->svgDocument->appendChild($this->svgGraphPane);
  867.  
  868.         if(count($this->svgToolTips->children)>0{
  869.             $this->svgDocument->appendChild($this->svgToolTips)
  870.         }
  871.     }
  872.     
  873.     // }}}
  874.     // SvgGrapher::drawHLine() {{{
  875.  
  876.     /**
  877.      * Draw an horizontal line.
  878.      *
  879.      * @param integer $value ordinate of the line.
  880.      * @param string $color line color.
  881.      * @return void 
  882.      */
  883.     public function drawHLine($value$color NULL$id NULL
  884.     {
  885.         $left 1;
  886.         $right $this->boxGraphPane->width - 2;
  887.  
  888.         if(is_null($color)) {
  889.             $color svgGrapher_internal_randomColor();
  890.         }
  891.         $style LIMITS_LINES_STYLE ' stroke:' $color ';';
  892.         $y $this->boxGraphPane->height - ($this->factorY * ($value $this->range['min']));
  893.         $line new LineElement(array(
  894.             'id' => $id,
  895.             'x1' => $left'y1' => $y
  896.             'x2' => $right'y2' => $y
  897.             'style'=>$style));
  898.         $this->svgGraphPane->appendChild($line);
  899.     }
  900.  
  901.     // }}}
  902.     // SvgGrapher::drawVLine() {{{
  903.  
  904.     /**
  905.      * Draw a vertical line (run checkChange before draw line).
  906.      *
  907.      * @param integer $value Tag name where draw the line.
  908.      * @param string $color line color.
  909.      * @return void 
  910.      */
  911.     public function drawVLine($value$color NULL$id NULL
  912.     {
  913.         $x 0;
  914.         $xOffset $value;
  915.         $top 0;
  916.         $bottom $this->boxGraphPane->height - 1;
  917.  
  918.           if(!empty($value)) {
  919.             if(is_null($color)) {
  920.                 $color svgGrapher_internal_randomColor();
  921.             }
  922.             $style LIMITS_LINES_STYLE ' stroke:' $color ';';
  923.             
  924.             foreach($this->tagsX as $idx => $tag{
  925.                 if($value == $tag{
  926.                     $xOffset $idx;
  927.                     break;
  928.                 }
  929.             }
  930.  
  931.             $x $this->gridLineXDelta * ($xOffset $this->plotOffsetX);
  932.             $line new LineElement(array('id' => $id,
  933.                 'x1' => $x'y1' => $top
  934.                 'x2' => $x'y2' => $bottom)$style);
  935.             $this->svgGraphPane->appendChild($line);
  936.           }
  937.  
  938.     }
  939.  
  940.     // }}}
  941.     // SvgGrapher::dumpSVG() {{{
  942.  
  943.     /**
  944.      * Write the svg in plain-text (to debug)
  945.      *
  946.      * @param string href to a CSS file.
  947.      * @return void 
  948.      */
  949.     public function dumpSVG($specifyCSS=NULL$prettyXML=false
  950.     {
  951.         header("Pragma: public");
  952.         header("Expires: 0");
  953.         header("Cache-Control: private");
  954.         header("Content-type: text/plain");
  955.         print($this->svgDocument->writeSVGString($specifyCSS$prettyXML));
  956.     }
  957.  
  958.     // }}}
  959.     // SvgGrapher::drawSVG() {{{
  960.  
  961.     /**
  962.      * Draw the svg or save it in file.
  963.      *
  964.      * @param string $filename file name to save svg in file.
  965.      * @param string href to a CSS file.
  966.      * @param boolean $prettyXML true to render pretty xml (unused if filename
  967.      *  is specified).
  968.      * @return void 
  969.      */
  970.     public function drawSVG($filename=NULL$specifyCSS=NULL$prettyXML=false
  971.     {
  972.         if(empty($filename)) {
  973.             header("Pragma: public");
  974.             header("Expires: 0");
  975.             header("Cache-Control: private");
  976.             header("Content-type: image/svg+xml");
  977.             //print($this->svgDocument->WriteSVGString($specifyCSS, $prettyXML));
  978.             print($this->svgDom->asPrettyXML());
  979.         else {
  980.             $this->svgDocument->WriteSVGFile($filename$specifyCSS$prettyXML);
  981.         }
  982.     }
  983.  
  984.     // }}}
  985.     // SvgGrapher::setDisplay() {{{
  986.     
  987.     /**
  988.      * setDisplay
  989.      *
  990.      * set the display property
  991.      *
  992.      * $value can be:
  993.      * - boolean: all the elements of the $display array take the value
  994.      * - array of string: the elements listed in the array take the value true
  995.      * - array of keys / values: for each element of the array, the elements of
  996.      * the $display array with the key take the value
  997.      * - string: the elements of the $display$ array take the value true
  998.      *
  999.      * examples:
  1000.      * <code>
  1001.      * $o = new SvgGrapher();
  1002.      * 
  1003.      * $o->display = false;
  1004.      * // all the elements in $display take the value false
  1005.      * 
  1006.      * $o->display = legend;
  1007.      * // $o->display['legend'] = true
  1008.      * 
  1009.      * $o->display = array('stepX', 'stepY');
  1010.      * // $o->display['stepX'] = true;
  1011.      * // $o->display['stepY'] = true;
  1012.      *
  1013.      * $o->display = array('labelX'=>false, 'labelY'=>true, 'title'=>true);
  1014.      * // $o->display['labelX'] = false;
  1015.      * // $o->display['labelY'] = true;
  1016.      * // $o->display['title'] = true;
  1017.      * </code>
  1018.      *
  1019.      * @param mixed $value 
  1020.      * @access public
  1021.      * @return void 
  1022.      */
  1023.     public function setDisplay($value
  1024.     {
  1025.         if(is_array($value)) {
  1026.             foreach($value as $k=>$v{
  1027.                 if(isset($this->display[$k])) {
  1028.                     $this->display[$k$v;
  1029.                 elseif(isset($this->display[$v])) {
  1030.                     $this->display[$vtrue;
  1031.                 }
  1032.             }
  1033.         elseif(is_bool($value)) {
  1034.             foreach($this->display as $k=>$v{
  1035.                 $this->display[$k$value;
  1036.             }
  1037.         elseif(is_string($value)) {
  1038.             $this->display[$valuetrue;
  1039.         }
  1040.         $this->_needUpdate = true;
  1041.     }
  1042.  
  1043.     // }}}
  1044. }
  1045.  
  1046. ?>

Documentation generated on Tue, 23 Oct 2007 11:32:14 +0200 by phpDocumentor 1.4.0