home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / HTML / Progress2.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  133.3 KB  |  3,813 lines

  1. <?php
  2. /**
  3.  * HTML loading bar with only PHP and JS interface.
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   HTML
  14.  * @package    HTML_Progress2
  15.  * @author     Laurent Laville <pear@laurent-laville.org>
  16.  * @copyright  1997-2005 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: Progress2.php,v 1.17 2005/09/25 16:19:11 farell Exp $
  19.  * @link       http://pear.php.net/package/HTML_Progress2
  20.  * @since      File available since Release 2.0.0RC1
  21.  */
  22.  
  23. require_once 'HTML/Common.php';
  24. require_once 'Event/Dispatcher.php';
  25. require_once 'PHP/Compat.php';
  26.  
  27. PHP_Compat::loadFunction('ob_get_clean');
  28. PHP_Compat::loadConstant('PHP_EOL');
  29.  
  30. /**#@+
  31.  * Progress Bar shape types
  32.  *
  33.  * @var        integer
  34.  * @since      2.0.0
  35.  */
  36. define ('HTML_PROGRESS2_BAR_HORIZONTAL', 1);
  37. define ('HTML_PROGRESS2_BAR_VERTICAL',   2);
  38. define ('HTML_PROGRESS2_POLYGONAL',      3);
  39. define ('HTML_PROGRESS2_CIRCLE',         4);
  40. /**#@-*/
  41.  
  42. /**#@+
  43.  * Progress Bar label types
  44.  *
  45.  * @var        string
  46.  * @since      2.0.0
  47.  */
  48. define ('HTML_PROGRESS2_LABEL_TEXT',     'text');
  49. define ('HTML_PROGRESS2_LABEL_BUTTON',   'button');
  50. define ('HTML_PROGRESS2_LABEL_STEP',     'step');
  51. define ('HTML_PROGRESS2_LABEL_PERCENT',  'percent');
  52. define ('HTML_PROGRESS2_LABEL_CROSSBAR', 'crossbar');
  53. /**#@-*/
  54.  
  55. /**
  56.  * Basic error code that indicate an unknown message
  57.  *
  58.  * @var        integer
  59.  * @since      2.0.0
  60.  */
  61. define ('HTML_PROGRESS2_ERROR_UNKNOWN',            -1);
  62.  
  63. /**
  64.  * Basic error code that indicate a wrong input
  65.  *
  66.  * @var        integer
  67.  * @since      2.0.0
  68.  */
  69. define ('HTML_PROGRESS2_ERROR_INVALID_INPUT',    -100);
  70.  
  71. /**
  72.  * Basic error code that indicate a wrong callback definition.
  73.  * Allows only function or class-method structure.
  74.  *
  75.  * @var        integer
  76.  * @since      2.0.0
  77.  */
  78. define ('HTML_PROGRESS2_ERROR_INVALID_CALLBACK', -101);
  79.  
  80. /**
  81.  * Basic error code that indicate a deprecated method
  82.  * that may be removed at any time from a future version
  83.  *
  84.  * @var        integer
  85.  * @since      2.0.0
  86.  */
  87. define ('HTML_PROGRESS2_ERROR_DEPRECATED',       -102);
  88.  
  89. /**
  90.  * Basic error code that indicate an invalid option.
  91.  *
  92.  * @var        integer
  93.  * @since      2.0.0
  94.  */
  95. define ('HTML_PROGRESS2_ERROR_INVALID_OPTION',   -103);
  96.  
  97.  
  98. /**
  99.  * HTML loading bar with only PHP and JS interface.
  100.  *
  101.  * The HTML_Progress2 class allow you to add a loading bar
  102.  * to any of your xhtml document.
  103.  * You should have a browser that accept DHTML feature.
  104.  *
  105.  * Here is a basic example:
  106.  * <code>
  107.  * <?php
  108.  * require_once 'HTML/Progress2.php';
  109.  *
  110.  * $pb = new HTML_Progress2();
  111.  * $pb->setAnimSpeed(50);
  112.  * ?>
  113.  * <html>
  114.  * <head>
  115.  * <?php
  116.  * echo $pb->getStyle(false);
  117.  * echo $pb->getScript(false);
  118.  * ?>
  119.  * </head>
  120.  * <body>
  121.  * <?php
  122.  * $pb->display();
  123.  * $pb->run();
  124.  * ?>
  125.  * </body>
  126.  * </html>
  127.  * </code>
  128.  *
  129.  * @category   HTML
  130.  * @package    HTML_Progress2
  131.  * @author     Laurent Laville <pear@laurent-laville.org>
  132.  * @copyright  1997-2005 The PHP Group
  133.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  134.  * @version    Release: 2.0.0
  135.  * @link       http://pear.php.net/package/HTML_Progress2
  136.  * @since      Class available since Release 2.0.0RC1
  137.  */
  138.  
  139. class HTML_Progress2 extends HTML_Common
  140. {
  141.     /**
  142.      * Status of the progress bar (new, show, hide).
  143.      *
  144.      * @var        string
  145.      * @since      2.0.0
  146.      * @access     private
  147.      */
  148.     var $_status = 'new';
  149.  
  150.     /**
  151.      * Whether the progress bar is in determinate or indeterminate mode.
  152.      * The default is false.
  153.      * An indeterminate progress bar continuously displays animation indicating
  154.      * that an operation of unknown length is occuring.
  155.      *
  156.      * @var        boolean
  157.      * @since      2.0.0
  158.      * @access     public
  159.      * @see        setIndeterminate(), isIndeterminate()
  160.      */
  161.     var $indeterminate;
  162.  
  163.     /**
  164.      * Whether to display a border around the progress bar.
  165.      * The default is false.
  166.      *
  167.      * @var        boolean
  168.      * @since      2.0.0
  169.      * @access     private
  170.      * @see        setBorderPainted(), isBorderPainted()
  171.      */
  172.     var $_paintBorder;
  173.  
  174.     /**
  175.      * The label that uniquely identifies this progress object.
  176.      *
  177.      * @var        string
  178.      * @since      2.0.0
  179.      * @access     public
  180.      * @see        getIdent(), setIdent()
  181.      */
  182.     var $ident;
  183.  
  184.     /**
  185.      * Stores the event dispatcher which handles notifications
  186.      *
  187.      * @var        array
  188.      * @since      2.0.0RC2
  189.      * @access     protected
  190.      */
  191.     var $dispatcher;
  192.  
  193.     /**
  194.      * Count the number of observer registered.
  195.      * The Event_Dispatcher will be add on first observer registration, and
  196.      * will be removed with the last observer.
  197.      *
  198.      * @var        integer
  199.      * @since      2.0.0RC2
  200.      * @access     private
  201.      */
  202.     var $_observerCount;
  203.  
  204.     /**
  205.      * Delay in milisecond before each progress cells display.
  206.      * 1000 ms === sleep(1)
  207.      * <strong>usleep()</strong> function does not run on Windows platform.
  208.      *
  209.      * @var        integer
  210.      * @since      2.0.0
  211.      * @access     public
  212.      * @see        setAnimSpeed()
  213.      */
  214.     var $animSpeed;
  215.  
  216.     /**
  217.      * Callback, either function name or array(&$object, 'method')
  218.      *
  219.      * @var        mixed
  220.      * @since      2.0.0
  221.      * @access     private
  222.      * @see        setProgressHandler()
  223.      */
  224.     var $_callback = false;
  225.  
  226.     /**
  227.      * The progress bar's minimum value.
  228.      * The default is 0.
  229.      *
  230.      * @var        integer
  231.      * @since      2.0.0
  232.      * @access     public
  233.      * @see        getMinimum(), setMinimum()
  234.      */
  235.     var $minimum;
  236.  
  237.     /**
  238.      * The progress bar's maximum value.
  239.      * The default is 100.
  240.      *
  241.      * @var        integer
  242.      * @since      2.0.0
  243.      * @access     public
  244.      * @see        getMaximum(), setMaximum()
  245.      */
  246.     var $maximum;
  247.  
  248.     /**
  249.      * The progress bar's increment value.
  250.      * The default is +1.
  251.      *
  252.      * @var        integer
  253.      * @since      2.0.0
  254.      * @access     public
  255.      * @see        getIncrement(), setIncrement()
  256.      */
  257.     var $increment;
  258.  
  259.     /**
  260.      * The progress bar's current value.
  261.      *
  262.      * @var        integer
  263.      * @since      2.0.0
  264.      * @access     public
  265.      * @see        getValue(), setvalue(), incValue()
  266.      */
  267.     var $value;
  268.  
  269.     /**
  270.      * Whether the progress bar is horizontal, vertical, polygonal or circle.
  271.      * The default is horizontal.
  272.      *
  273.      * @var        integer
  274.      * @since      2.0.0
  275.      * @access     public
  276.      * @see        getOrientation(), setOrientation()
  277.      */
  278.     var $orientation;
  279.  
  280.     /**
  281.      * Whether the progress bar is filled in 'natural' or 'reverse' way.
  282.      * The default fill way is 'natural'.
  283.      *
  284.      * <ul>
  285.      * <li>'way'  =  bar fill way
  286.      *   <ul>
  287.      *     <li>with Progress Bar Horizontal,
  288.      *              natural way is : left to right
  289.      *        <br />reverse way is : right to left
  290.      *     <li>with Progress Bar Vertical,
  291.      *              natural way is : down to up
  292.      *        <br />reverse way is : up to down
  293.      *     <li>with Progress Circle or Polygonal,
  294.      *              natural way is : clockwise
  295.      *        <br />reverse way is : anticlockwise
  296.      *   </ul>
  297.      * </ul>
  298.      *
  299.      * @var        string
  300.      * @since      2.0.0
  301.      * @access     public
  302.      * @see        getFillWay(), setFillWay()
  303.      */
  304.     var $fillWay;
  305.  
  306.     /**
  307.      * The cell count of the progress bar. The default is 10.
  308.      *
  309.      * @var        integer
  310.      * @since      2.0.0
  311.      * @access     public
  312.      * @see        getCellCount(), setCellCount()
  313.      */
  314.     var $cellCount;
  315.  
  316.     /**
  317.      * The cell coordinates for a progress polygonal shape.
  318.      *
  319.      * @var        array
  320.      * @since      2.0.0
  321.      * @access     private
  322.      * @see        getCellCoordinates(), setCellCoordinates()
  323.      */
  324.     var $_coordinates;
  325.  
  326.     /**
  327.      * The width of grid in cell-size of the polygonal shape.
  328.      *
  329.      * @var        integer
  330.      * @since      2.0.0
  331.      * @access     private
  332.      * @see        getCellCoordinates(), setCellCoordinates()
  333.      */
  334.     var $_xgrid;
  335.  
  336.     /**
  337.      * The height of grid in cell-size of the polygonal shape.
  338.      *
  339.      * @var        integer
  340.      * @since      2.0.0
  341.      * @access     private
  342.      * @see        getCellCoordinates(), setCellCoordinates()
  343.      */
  344.     var $_ygrid;
  345.  
  346.     /**
  347.      * Progress bar core properties
  348.      *
  349.      * <code>
  350.      * $progress = array(
  351.      *    'background-color' => '#FFFFFF',      # bar background color
  352.      *    'background-image' => 'none',         # bar background image
  353.      *    'background-repeat' => 'no-repeat',   # bar background image repeat option
  354.      *    'background-position' => 'top left',  # bar background image start position
  355.      *    'width' => 0,                     # bar width
  356.      *    'height' => 0,                    # bar height
  357.      *    'left' => 10,                     # position from left
  358.      *    'top' => 25,                      # position from top
  359.      *    'position' => 'relative'          # position absolute or relative
  360.      * );
  361.      * </code>
  362.      *
  363.      * @var        array
  364.      * @since      2.0.0
  365.      * @access     private
  366.      * @see        getProgressAttributes(), setProgressAttributes()
  367.      */
  368.     var $_progress = array();
  369.  
  370.     /**
  371.      * Progress bar frame properties
  372.      *
  373.      * <code>
  374.      * $frame = array(
  375.      *    'show' => false,      # frame show (true/false)
  376.      *    'left' => 200,        # position from left
  377.      *    'top' => 100,         # position from top
  378.      *    'width' => 320,       # width
  379.      *    'height' => 90,       # height
  380.      *    'color' => '#C0C0C0', # color
  381.      *    'border-width' => 2,                                   # border width
  382.      *    'border-style' => 'solid',                             # border style
  383.      *                                                           # (solid, dashed, dotted ...)
  384.      *    'border-color' => '#DFDFDF #404040 #404040 #DFDFDF'    # border color (3dfx)
  385.      * );
  386.      * </code>
  387.      *
  388.      * @var        array
  389.      * @since      2.0.0
  390.      * @access     public
  391.      * @see        getFrameAttributes(), setFrameAttributes()
  392.      */
  393.     var $frame = array();
  394.  
  395.     /**
  396.      * Progress bar border properties
  397.      *
  398.      * <code>
  399.      * $border = array(
  400.      *    'class' => 'progressBorder%s',    # css class selector
  401.      *    'width' => 0,                     # width size in pixel
  402.      *    'style' => 'solid',               # style (solid, dashed, dotted ...)
  403.      *    'color' => '#000000'              # color
  404.      * );
  405.      * </code>
  406.      *
  407.      * @var        array
  408.      * @since      2.0.0
  409.      * @access     public
  410.      * @see        getBorderAttributes(), setBorderAttributes()
  411.      */
  412.     var $border = array();
  413.  
  414.     /**
  415.      * Progress bar cells properties
  416.      *
  417.      * <code>
  418.      * $cell = array(
  419.      *    'id' => 'pcel%01s',                    # cell identifier mask
  420.      *    'class' => 'cell%s',                   # css class selector
  421.      *    'active-color' => '#006600',           # active color
  422.      *    'inactive-color' => '#CCCCCC',         # inactive color
  423.      *    'font-family' => 'Courier, Verdana',   # font family
  424.      *    'font-size' => 8,                      # font size
  425.      *    'color' => '#000000',                  # foreground color
  426.      *    'background-color' => '#FFFFFF',       # background color
  427.      *    'background-image' => 'none',          # cell background image
  428.      *    'background-repeat' => 'no-repeat',    # cell background image repeat option
  429.      *    'background-position' => 'top left',   # cell background image start position
  430.      *    'width' => 15,                         # cell width
  431.      *    'height' => 20,                        # cell height
  432.      *    'spacing' => 2                         # cell spacing
  433.      * );
  434.      * </code>
  435.      *
  436.      * @var        array
  437.      * @since      2.0.0
  438.      * @access     public
  439.      * @see        getCellAttributes(), setCellAttributes()
  440.      */
  441.     var $cell = array();
  442.  
  443.     /**
  444.      * Progress bar labels properties
  445.      *
  446.      * <code>
  447.      * $label = array(
  448.      *    'name' => array(                  # label name
  449.      *      'type' => 'text',               # label type
  450.      *                                      # (text,button,step,percent,crossbar)
  451.      *      'value' => ' ',            # label value
  452.      *      'left' => ($left),              # label position from left
  453.      *      'top' => ($top - 16),           # label position from top
  454.      *      'width' => 0,                   # label width
  455.      *      'height' => 0,                  # label height
  456.      *      'align' => 'left',              # label align
  457.      *      'background-color' => 'transparent',          # label background color
  458.      *      'font-family' => 'Verdana, Tahoma, Arial',    # label font family
  459.      *      'font-size' => 11,                            # label font size
  460.      *      'font-weight' => 'normal',                    # label font weight
  461.      *      'color' => '#000000',                         # label font color
  462.      *      'class' => 'progressPercentLabel%s'           # css class selector
  463.      * );
  464.      * </code>
  465.      *
  466.      * @var        array
  467.      * @since      2.0.0
  468.      * @access     public
  469.      * @see        getLabelAttributes(), setLabelAttributes()
  470.      */
  471.     var $label = array();
  472.  
  473.     /**
  474.      * External Javascript file to override internal default code
  475.      *
  476.      * @var        string
  477.      * @since      2.0.0
  478.      * @access     public
  479.      * @see        getScript(), setScript()
  480.      */
  481.     var $script;
  482.  
  483.     /**
  484.      * Error message callback.
  485.      * This will be used to generate the error message
  486.      * from the error code.
  487.      *
  488.      * @var        false|string|array
  489.      * @since      2.0.0
  490.      * @access     private
  491.      * @see        _initErrorHandler()
  492.      */
  493.     var $_callback_message = false;
  494.  
  495.     /**
  496.      * Error context callback.
  497.      * This will be used to generate the error context for an error.
  498.      *
  499.      * @var        false|string|array
  500.      * @since      2.0.0
  501.      * @access     private
  502.      * @see        _initErrorHandler()
  503.      */
  504.     var $_callback_context = false;
  505.  
  506.     /**
  507.      * Error push callback.
  508.      * The return value will be used to determine whether to allow
  509.      * an error to be pushed or logged.
  510.      *
  511.      * @var        false|string|array
  512.      * @since      2.0.0
  513.      * @access     private
  514.      * @see        _initErrorHandler()
  515.      */
  516.     var $_callback_push = false;
  517.  
  518.     /**
  519.      * Error handler callback.
  520.      * This will handle any errors raised by this package.
  521.      *
  522.      * @var        false|string|array
  523.      * @since      2.0.0
  524.      * @access     private
  525.      * @see        _initErrorHandler()
  526.      */
  527.     var $_callback_errorhandler = false;
  528.  
  529.     /**
  530.      * Associative array of key-value pairs
  531.      * that are used to specify any handler-specific settings.
  532.      *
  533.      * @var        array
  534.      * @since      2.0.0
  535.      * @access     private
  536.      * @see        _initErrorHandler()
  537.      */
  538.     var $_errorhandler_options = array();
  539.  
  540.     /**
  541.      * Error stack for this package.
  542.      *
  543.      * @var        array
  544.      * @since      2.0.0
  545.      * @access     private
  546.      * @see        raiseError()
  547.      */
  548.     var $_errorstack = array();
  549.  
  550.  
  551.     /**
  552.      * Constructor (ZE1)
  553.      *
  554.      * @since      2.0.0
  555.      * @access     public
  556.      */
  557.     function HTML_Progress2($errorPrefs = array(),
  558.                             $orient = HTML_PROGRESS2_BAR_HORIZONTAL, $min = 0, $max = 100,
  559.                             $percentLabel = 'pct1')
  560.     {
  561.         $this->__construct($errorPrefs, $orient, $min, $max, $percentLabel);
  562.     }
  563.  
  564.     /**
  565.      * Constructor (ZE2) Summary
  566.      *
  567.      *   Creates a natural horizontal progress bar that displays ten separated cells
  568.      *   with no border and only percent label.
  569.      *   The initial and minimum values are 0, and the maximum is 100.
  570.      *
  571.      * @param      array     $errorPrefs    (optional) Hash of params to configure error handler
  572.      * @param      int       $orient        (optional) Orientation of progress bar
  573.      * @param      int       $min           (optional) Minimum value of progress bar
  574.      * @param      int       $max           (optional) Maximum value of progress bar
  575.      * @param      mixed     $percentLabel  (optional) Progress bar percent label id.
  576.      *
  577.      * @since      2.0.0
  578.      * @access     protected
  579.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  580.      * @see        setIndeterminate(), setIdent(), setAnimSpeed(),
  581.      *             setOrientation(), setMinimum(), setMaximum(), addLabel()
  582.      */
  583.     function __construct($errorPrefs = array(),
  584.                          $orient = HTML_PROGRESS2_BAR_HORIZONTAL, $min = 0, $max = 100,
  585.                          $percentLabel = 'pct1')
  586.     {
  587.         $this->_initErrorHandler($errorPrefs);
  588.  
  589.         $this->_observerCount = 0;
  590.  
  591.         $this->value = 0;
  592.         $this->minimum = 0;
  593.         $this->maximum = 100;
  594.         $this->increment = +1;
  595.  
  596.         $this->cellCount = 10;
  597.         $this->orientation = HTML_PROGRESS2_BAR_HORIZONTAL;
  598.         $this->fillWay = 'natural';         // fill bar from left to right
  599.         $this->script = null;               // uses internal javascript code
  600.  
  601.         $this->frame  = array('show' => false);
  602.         $this->_progress = array(
  603.             'background-color' => '#FFFFFF',
  604.             'background-image' => 'none',
  605.             'background-repeat' => 'no-repeat',
  606.             'background-position' => 'top left',
  607.             'width' => 0,
  608.             'height' => 0,
  609.             'left' => 10,
  610.             'top' => 25,
  611.             'position' => 'relative'
  612.         );
  613.         $this->border = array(
  614.             'class' => 'progressBorder%s',
  615.             'width' => 0,
  616.             'style' => 'solid',
  617.             'color' => '#000000'
  618.         );
  619.         $this->cell = array(
  620.             'id' => 'pcel%01s',
  621.             'class' => 'cell%s',
  622.             'active-color' => '#006600',
  623.             'inactive-color' => '#CCCCCC',
  624.             'font-family' => 'Courier, Verdana',
  625.             'font-size' => 8,
  626.             'color' => '#000000',
  627.             'background-color' => '#FFFFFF',
  628.             'background-image' => 'none',
  629.             'background-repeat' => 'no-repeat',
  630.             'background-position' => 'top left',
  631.             'width' => 15,
  632.             'height' => 20,
  633.             'spacing' => 2
  634.         );
  635.  
  636.         $this->_updateProgressSize();   // updates the new size of progress bar
  637.  
  638.         if (!is_int($orient)) {
  639.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  640.                 array('var' => '$orient',
  641.                       'was' => gettype($orient),
  642.                       'expected' => 'integer',
  643.                       'paramnum' => 2));
  644.  
  645.         } elseif (!is_int($min)) {
  646.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  647.                 array('var' => '$min',
  648.                       'was' => gettype($min),
  649.                       'expected' => 'integer',
  650.                       'paramnum' => 3));
  651.  
  652.         } elseif (!is_int($max)) {
  653.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  654.                 array('var' => '$max',
  655.                       'was' => gettype($max),
  656.                       'expected' => 'integer',
  657.                       'paramnum' => 4));
  658.  
  659.         } elseif (!is_string($percentLabel) && !is_bool($percentLabel)) {
  660.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  661.                 array('var' => '$percentLabel',
  662.                       'was' => gettype($percentLabel),
  663.                       'expected' => 'string | boolean',
  664.                       'paramnum' => 5));
  665.         }
  666.  
  667.         $this->setOrientation($orient);
  668.         $this->setMinimum($min);
  669.         $this->setMaximum($max);
  670.  
  671.         if ($percentLabel) {
  672.             $this->addLabel(HTML_PROGRESS2_LABEL_PERCENT, $percentLabel);
  673.         }
  674.         $this->setBorderPainted(false);
  675.         $this->setIndeterminate(false);
  676.         $this->setIdent();
  677.         $this->setAnimSpeed(0);
  678.  
  679.         // to fix a potential php config problem with PHP 4.2.0 : turn 'implicit_flush' ON
  680.         ob_implicit_flush(1);
  681.     }
  682.  
  683.     /**
  684.      * Returns the current API version.
  685.      *
  686.      * This function return a "PHP-standardized" version number string.
  687.      * This is useful if you would like to write programs working only on some
  688.      * versions of HTML_Progress2. See also php version_compare() function.
  689.      *
  690.      * @link       http://www.php.net/manual/en/function.version-compare.php
  691.      * @return     string
  692.      * @since      2.0.0
  693.      * @access     public
  694.      */
  695.     function apiVersion()
  696.     {
  697.         return '2.0.0';
  698.     }
  699.  
  700.     /**
  701.      * Returns mode of the progress meter.
  702.      *
  703.      * There are two types of progress meters: determinate and undeterminate.
  704.      *
  705.      * Determinate progress meters are used when you know the length of time
  706.      * that an operation will take. The progress meter will fill up and,
  707.      * once full, the operation should be finished.
  708.      *
  709.      * Undeterminate progress meters are used when you do not know the length
  710.      * of time of an operation. The progress meter will have an animation
  711.      * such a sliding box.
  712.      *
  713.      * @return     boolean
  714.      * @since      2.0.0
  715.      * @access     public
  716.      * @see        setIndeterminate()
  717.      */
  718.     function isIndeterminate()
  719.     {
  720.         return $this->indeterminate;
  721.     }
  722.  
  723.     /**
  724.      * Sets the mode of progress meter.
  725.      *
  726.      * Default progress meters are in determinate mode ($continuous = TRUE), but
  727.      * can be switched anytime in indeterminate mode ($continuous = FALSE).
  728.      *
  729.      * @param      boolean   $continuous    whether countinuously displays animation
  730.      *
  731.      * @return     void
  732.      * @since      2.0.0
  733.      * @access     public
  734.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  735.      * @see        isIndeterminate()
  736.      */
  737.     function setIndeterminate($continuous)
  738.     {
  739.         if (!is_bool($continuous)) {
  740.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  741.                 array('var' => '$continuous',
  742.                       'was' => gettype($continuous),
  743.                       'expected' => 'boolean',
  744.                       'paramnum' => 1));
  745.         }
  746.         $this->indeterminate = $continuous;
  747.     }
  748.  
  749.     /**
  750.      * Determines whether the progress bar border is painted or not.
  751.      *
  752.      * By default, each progress bar (horizontal, vertical) has no border.
  753.      * This function gave ability to know if you've already set a border
  754.      * (return TRUE), or not (return FALSE).
  755.      *
  756.      * @return     boolean
  757.      * @since      2.0.0
  758.      * @access     public
  759.      * @see        setBorderPainted()
  760.      */
  761.     function isBorderPainted()
  762.     {
  763.         return $this->_paintBorder;
  764.     }
  765.  
  766.     /**
  767.      * Decides to paint or not a border to the progress bar.
  768.      *
  769.      * This function gave ability to set ($paint = TRUE) or remove ($paint = FALSE)
  770.      * a border to the current progress bar.
  771.      *
  772.      * @param      boolean   $paint         whether the progress bar should paint its border
  773.      *
  774.      * @return     void
  775.      * @since      2.0.0
  776.      * @access     public
  777.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  778.      * @see        isBorderPainted()
  779.      */
  780.     function setBorderPainted($paint)
  781.     {
  782.         if (!is_bool($paint)) {
  783.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  784.                 array('var' => '$paint',
  785.                       'was' => gettype($paint),
  786.                       'expected' => 'boolean',
  787.                       'paramnum' => 1));
  788.         }
  789.  
  790.         $this->_paintBorder = $paint;
  791.     }
  792.  
  793.     /**
  794.      * Returns the progress meter minimum value.
  795.      *
  796.      * Get the minimum value at which the progress meter will start.
  797.      * The default value is zero and can't be negative.
  798.      *
  799.      * @return     integer
  800.      * @since      2.0.0
  801.      * @access     public
  802.      * @see        setMinimum()
  803.      */
  804.     function getMinimum()
  805.     {
  806.         return $this->minimum;
  807.     }
  808.  
  809.     /**
  810.      * Sets the progress meter minimum value.
  811.      *
  812.      * Set the minimum value at which the progress meter will start.
  813.      * The default value is zero and can't be negative.
  814.      * If the new minimum is different than previous value, all listeners
  815.      * are notified.
  816.      *
  817.      * @param      integer   $min           progress meter's minimal value
  818.      *
  819.      * @return     void
  820.      * @since      2.0.0
  821.      * @access     public
  822.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  823.      * @see        getMinimum()
  824.      */
  825.     function setMinimum($min)
  826.     {
  827.         if (!is_int($min)) {
  828.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  829.                 array('var' => '$min',
  830.                       'was' => gettype($min),
  831.                       'expected' => 'integer',
  832.                       'paramnum' => 1));
  833.  
  834.         } elseif ($min < 0) {
  835.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  836.                 array('var' => '$min',
  837.                       'was' => $min,
  838.                       'expected' => 'positive',
  839.                       'paramnum' => 1));
  840.  
  841.         } elseif ($min > $this->maximum) {
  842.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  843.                 array('var' => '$min',
  844.                       'was' => $min,
  845.                       'expected' => 'less than $max = '.$this->maximum,
  846.                       'paramnum' => 1));
  847.         }
  848.         $oldVal = $this->minimum;
  849.         $this->minimum = $min;
  850.  
  851.         /* set current value to minimum if less than minimum */
  852.         if ($this->value < $min) {
  853.             $this->setValue($min);
  854.         }
  855.  
  856.         if ($oldVal != $min) {
  857.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $min));
  858.         }
  859.     }
  860.  
  861.     /**
  862.      * Returns the progress meter maximum value.
  863.      *
  864.      * Get the maximum value at which the progress meter will stop.
  865.      * The default value is 100 and can't be less than minimum.
  866.      *
  867.      * @return     integer
  868.      * @since      2.0.0
  869.      * @access     public
  870.      * @see        setMaximum()
  871.      */
  872.     function getMaximum()
  873.     {
  874.         return $this->maximum;
  875.     }
  876.  
  877.     /**
  878.      * Sets the progress meter maximum value.
  879.      *
  880.      * Set the maximum value at which the progress meter will stop.
  881.      * The default value is 100 and can't be less than minimum.
  882.      * If the new maximum is different than previous value, all listeners
  883.      * are notified.
  884.      *
  885.      * @param      integer   $max           progress meter's maximal value
  886.      *
  887.      * @return     void
  888.      * @since      2.0.0
  889.      * @access     public
  890.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  891.      * @see        getMaximum()
  892.      */
  893.     function setMaximum($max)
  894.     {
  895.         if (!is_int($max)) {
  896.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  897.                 array('var' => '$max',
  898.                       'was' => gettype($max),
  899.                       'expected' => 'integer',
  900.                       'paramnum' => 1));
  901.  
  902.         } elseif ($max < 0) {
  903.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  904.                 array('var' => '$max',
  905.                       'was' => $max,
  906.                       'expected' => 'positive',
  907.                       'paramnum' => 1));
  908.  
  909.         } elseif ($max < $this->minimum) {
  910.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  911.                 array('var' => '$max',
  912.                       'was' => $max,
  913.                       'expected' => 'greater than $min = '.$this->minimum,
  914.                       'paramnum' => 1));
  915.         }
  916.         $oldVal = $this->maximum;
  917.         $this->maximum = $max;
  918.  
  919.         /* set current value to maximum if greater to maximum */
  920.         if ($this->value > $max) {
  921.             $this->setValue($max);
  922.         }
  923.  
  924.         if ($oldVal != $max) {
  925.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $max));
  926.         }
  927.     }
  928.  
  929.     /**
  930.      * Returns the progress meter increment value.
  931.      *
  932.      * Get step of progress property of a progress meter.
  933.      * The default value is +1.
  934.      *
  935.      * @return     integer
  936.      * @since      2.0.0
  937.      * @access     public
  938.      * @see        setIncrement()
  939.      */
  940.     function getIncrement()
  941.     {
  942.         return $this->increment;
  943.     }
  944.  
  945.     /**
  946.      * Sets the progress meter increment value.
  947.      *
  948.      * Defines step of progress property of a progress meter.
  949.      * Allows to ajust default value (+1).
  950.      *
  951.      * @param      integer   $inc           progress meter's increment value
  952.      *
  953.      * @return     void
  954.      * @since      2.0.0
  955.      * @access     public
  956.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  957.      * @see        getIncrement()
  958.      */
  959.     function setIncrement($inc)
  960.     {
  961.         if (!is_int($inc)) {
  962.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  963.                 array('var' => '$inc',
  964.                       'was' => gettype($inc),
  965.                       'expected' => 'integer',
  966.                       'paramnum' => 1));
  967.  
  968.         } elseif ($inc == 0) {
  969.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  970.                 array('var' => '$inc',
  971.                       'was' => $inc,
  972.                       'expected' => 'not equal zero',
  973.                       'paramnum' => 1));
  974.         }
  975.         $this->increment = $inc;
  976.     }
  977.  
  978.     /**
  979.      * Returns the progress meter current value.
  980.      *
  981.      * Get the current value of the progress meter that is always between
  982.      * the minimum and maximum values, inclusive.
  983.      * The default value is equal to minimum.
  984.      *
  985.      * @return     integer
  986.      * @since      2.0.0
  987.      * @access     public
  988.      * @see        setValue(), incValue()
  989.      */
  990.     function getValue()
  991.     {
  992.         return $this->value;
  993.     }
  994.  
  995.     /**
  996.      * Sets the progress meter current value.
  997.      *
  998.      * Set the current value of the progress meter that is always between
  999.      * the minimum and maximum values, inclusive. If the new value is different
  1000.      * from previous, then all listeners are notified.
  1001.      *
  1002.      * @param      integer   $val           progress meter's current value
  1003.      *
  1004.      * @return     void
  1005.      * @since      2.0.0
  1006.      * @access     public
  1007.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1008.      * @see        getValue(), incValue()
  1009.      */
  1010.     function setValue($val)
  1011.     {
  1012.         if (!is_int($val)) {
  1013.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1014.                 array('var' => '$val',
  1015.                       'was' => gettype($val),
  1016.                       'expected' => 'integer',
  1017.                       'paramnum' => 1));
  1018.  
  1019.         } elseif ($val < $this->minimum) {
  1020.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1021.                 array('var' => '$val',
  1022.                       'was' => $val,
  1023.                       'expected' => 'greater than $min = '.$this->minimum,
  1024.                       'paramnum' => 1));
  1025.  
  1026.         } elseif ($val > $this->maximum) {
  1027.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1028.                 array('var' => '$val',
  1029.                       'was' => $val,
  1030.                       'expected' => 'less than $max = '.$this->maximum,
  1031.                       'paramnum' => 1));
  1032.         }
  1033.         $oldVal = $this->value;
  1034.         $this->value = $val;
  1035.  
  1036.         if ($oldVal != $val) {
  1037.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $val));
  1038.         }
  1039.     }
  1040.  
  1041.     /**
  1042.      * Updates the internal progress meter current value.
  1043.      *
  1044.      * The new current value is equal to previous value increase by
  1045.      * increment value. All listeners are notified.
  1046.      * See also moveNext() method if you want a refresh display too.
  1047.      *
  1048.      * @return     void
  1049.      * @since      2.0.0
  1050.      * @access     public
  1051.      * @see        getValue(), setValue(), moveNext()
  1052.      */
  1053.     function incValue()
  1054.     {
  1055.         $newVal = $this->value + $this->increment;
  1056.         $newVal = min($this->maximum, $newVal);
  1057.         $this->value = $newVal;
  1058.  
  1059.         $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $newVal));
  1060.     }
  1061.  
  1062.     /**
  1063.      * Changes new value of the progress meter by step increase.
  1064.      *
  1065.      * Move current value to the next step of the progress meter
  1066.      * defined by its increment. If result value is different than previous,
  1067.      * then all listeners are notified.
  1068.      * Caution: a step is always between 1 and (maximum / taskcount) rounded fractions up.
  1069.      *
  1070.      * @param      integer   $step          new step value
  1071.      *
  1072.      * @return     void
  1073.      * @since      2.0.0
  1074.      * @access     public
  1075.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1076.      * @see        moveNext()
  1077.      */
  1078.     function moveStep($step)
  1079.     {
  1080.         if (!is_int($step)) {
  1081.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1082.                 array('var' => '$step',
  1083.                       'was' => gettype($step),
  1084.                       'expected' => 'integer',
  1085.                       'paramnum' => 1));
  1086.  
  1087.         } elseif ($step < 0) {
  1088.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1089.                 array('var' => '$step',
  1090.                       'was' => $step,
  1091.                       'expected' => 'greater than zero',
  1092.                       'paramnum' => 1));
  1093.  
  1094.         } elseif ($step > intval(ceil($this->maximum / $this->increment))) {
  1095.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1096.                 array('var' => '$step',
  1097.                       'was' => $step,
  1098.                       'expected' => 'less than '. intval(ceil($this->maximum / $this->increment)),
  1099.                       'paramnum' => 1));
  1100.         }
  1101.         $oldVal = $this->value;
  1102.         $this->value = $step * $this->increment;
  1103.         $this->value = min($this->maximum, $this->value);
  1104.  
  1105.         if ($oldVal != $this->value) {
  1106.             $this->_refreshDisplay($this->value);
  1107.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $step));
  1108.         }
  1109.     }
  1110.  
  1111.     /**
  1112.      * Changes new value of the progress meter by increment increase.
  1113.      *
  1114.      * Move current value to the next value of the progress meter
  1115.      * defined by its increment. If result value is different than previous,
  1116.      * then all listeners are notified.
  1117.      *
  1118.      * @return     void
  1119.      * @since      2.0.0
  1120.      * @access     public
  1121.      * @see        moveStep()
  1122.      */
  1123.     function moveNext()
  1124.     {
  1125.         $oldVal = $this->value;
  1126.         $this->value  = $oldVal + $this->increment;
  1127.         $this->value = min($this->maximum, $this->value);
  1128.  
  1129.         if ($oldVal != $this->value) {
  1130.             $this->_refreshDisplay($this->value);
  1131.             $this->_postNotification('onChange', array('handler' => __FUNCTION__, 'value' => $this->value));
  1132.         }
  1133.     }
  1134.  
  1135.     /**
  1136.      * Returns the percent complete of the progress meter.
  1137.      *
  1138.      * Note that this number is between 0.00 and 1.00 when $float = true.
  1139.      * And this number is between 0 and 100 when $float = false.
  1140.      *
  1141.      * @param      boolean   $float         (optional) float or integer format
  1142.      *
  1143.      * @return     float
  1144.      * @since      2.0.0
  1145.      * @access     public
  1146.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1147.      * @see        getValue(), getMaximum()
  1148.      */
  1149.     function getPercentComplete($float = true)
  1150.     {
  1151.         if (!is_bool($float)) {
  1152.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1153.                 array('var' => '$float',
  1154.                       'was' => gettype($float),
  1155.                       'expected' => 'boolean',
  1156.                       'paramnum' => 1));
  1157.         }
  1158.  
  1159.         $min = $this->minimum;
  1160.         $max = $this->maximum;
  1161.         $val = $this->value;
  1162.  
  1163.         $percent = round((($val - $min) / ($max - $min)), 4);
  1164.  
  1165.         if ($float) {
  1166.             return $percent;
  1167.         } else {
  1168.             return intval($percent * 100);
  1169.         }
  1170.     }
  1171.  
  1172.     /**
  1173.      * Returns orientation of the progress bar.
  1174.      *
  1175.      * There are only two distinct orientations for a progress bar:
  1176.      * horizontal and vertical, identified by two constants:
  1177.      * HTML_PROGRESS2_BAR_HORIZONTAL and HTML_PROGRESS2_BAR_VERTICAL.
  1178.      * While circle and other polygonal progress meter are identified by
  1179.      * two other constants: HTML_PROGRESS2_CIRCLE and HTML_PROGRESS2_POLYGONAL.
  1180.      * The default orientation is horizontal.
  1181.      *
  1182.      * @return     integer
  1183.      * @since      2.0.0
  1184.      * @access     public
  1185.      * @see        setOrientation()
  1186.      */
  1187.     function getOrientation()
  1188.     {
  1189.         return $this->orientation;
  1190.     }
  1191.  
  1192.     /**
  1193.      * Sets orientation of the progress bar.
  1194.      *
  1195.      * There are only two distinct orientations for a progress bar:
  1196.      * horizontal and vertical, identified by two constants:
  1197.      * HTML_PROGRESS2_BAR_HORIZONTAL and HTML_PROGRESS2_BAR_VERTICAL.
  1198.      * While circle and other polygonal progress meter are identified by
  1199.      * two other constants: HTML_PROGRESS2_CIRCLE and HTML_PROGRESS2_POLYGONAL.
  1200.      * The default orientation is horizontal.
  1201.      *
  1202.      * @param      integer   $orient        Orientation (horizontal or vertical)
  1203.      *
  1204.      * @return     void
  1205.      * @since      2.0.0
  1206.      * @access     public
  1207.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1208.      * @see        getOrientation()
  1209.      */
  1210.     function setOrientation($orient)
  1211.     {
  1212.         if (!is_int($orient)) {
  1213.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1214.                 array('var' => '$orient',
  1215.                       'was' => gettype($orient),
  1216.                       'expected' => 'integer',
  1217.                       'paramnum' => 1));
  1218.  
  1219.         } elseif (($orient != HTML_PROGRESS2_BAR_HORIZONTAL) &&
  1220.                   ($orient != HTML_PROGRESS2_BAR_VERTICAL) &&
  1221.                   ($orient != HTML_PROGRESS2_POLYGONAL) &&
  1222.                   ($orient != HTML_PROGRESS2_CIRCLE)) {
  1223.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1224.                 array('var' => '$orient',
  1225.                       'was' => $orient,
  1226.                       'expected' => HTML_PROGRESS2_BAR_HORIZONTAL.' | '.
  1227.                                     HTML_PROGRESS2_BAR_VERTICAL.' | '.
  1228.                                     HTML_PROGRESS2_POLYGONAL.' | '.
  1229.                                     HTML_PROGRESS2_CIRCLE,
  1230.                       'paramnum' => 1));
  1231.         }
  1232.  
  1233.         $previous = $this->orientation;    // gets previous orientation
  1234.         $this->orientation = $orient;      // sets the new orientation
  1235.  
  1236.         if ($previous != $orient) {
  1237.             // if orientation has changed, we need to swap cell width and height
  1238.             $w = $this->cell['width'];
  1239.             $h = $this->cell['height'];
  1240.  
  1241.             $this->cell['width']  = $h;
  1242.             $this->cell['height'] = $w;
  1243.  
  1244.             $this->_updateProgressSize();   // updates the new size of progress bar
  1245.         }
  1246.     }
  1247.  
  1248.     /**
  1249.      * Returns fill option of the progress meter.
  1250.      *
  1251.      * Get 'natural' or 'reverse', depending of the fill way of progress meter.
  1252.      * For horizontal progress bar, natural way is from left to right, and reverse
  1253.      * way is from right to left.
  1254.      * For vertical progress bar, natural way is from down to up, and reverse
  1255.      * way is from up to down.
  1256.      * The default fill way is 'natural'.
  1257.      *
  1258.      * @return     string
  1259.      * @since      2.0.0
  1260.      * @access     public
  1261.      * @see        setFillWay()
  1262.      */
  1263.     function getFillWay()
  1264.     {
  1265.         return $this->fillWay;
  1266.     }
  1267.  
  1268.     /**
  1269.      * Sets fill option of the progress meter.
  1270.      *
  1271.      * Sets the progress meter fill option: must be 'natural' or 'reverse'.
  1272.      * The default fill way is 'natural'.
  1273.      *
  1274.      * @param      string    $way           fill direction (natural or reverse)
  1275.      *
  1276.      * @return     void
  1277.      * @since      2.0.0
  1278.      * @access     public
  1279.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1280.      * @see        getFillWay()
  1281.      */
  1282.     function setFillWay($way)
  1283.     {
  1284.         if (!is_string($way)) {
  1285.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1286.                 array('var' => '$way',
  1287.                       'was' => gettype($way),
  1288.                       'expected' => 'string',
  1289.                       'paramnum' => 1));
  1290.  
  1291.         } elseif (($way != 'natural') && ($way != 'reverse')) {
  1292.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1293.                 array('var' => '$way',
  1294.                       'was' => $way,
  1295.                       'expected' => 'natural | reverse',
  1296.                       'paramnum' => 1));
  1297.  
  1298.         }
  1299.         $this->fillWay = $way;
  1300.     }
  1301.  
  1302.     /**
  1303.      * Returns count of cell in the progress meter.
  1304.      *
  1305.      * Get the number of cell defined to a progress meter. It must be positive.
  1306.      * The default value is 10.
  1307.      *
  1308.      * @return     integer
  1309.      * @since      2.0.0
  1310.      * @access     public
  1311.      * @see        setCellCount()
  1312.      */
  1313.     function getCellCount()
  1314.     {
  1315.         return $this->cellCount;
  1316.     }
  1317.  
  1318.     /**
  1319.      * Sets count of cell in the progress meter.
  1320.      *
  1321.      * Defines the number of cell to a progress meter. It must be positive.
  1322.      * The default value is 10.
  1323.      *
  1324.      * @param      integer   $cells         Cell count on progress meter
  1325.      *
  1326.      * @return     void
  1327.      * @since      2.0.0
  1328.      * @access     public
  1329.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1330.      * @see        getCellCount()
  1331.      */
  1332.     function setCellCount($cells)
  1333.     {
  1334.         if (!is_int($cells)) {
  1335.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1336.                 array('var' => '$cells',
  1337.                       'was' => gettype($cells),
  1338.                       'expected' => 'integer',
  1339.                       'paramnum' => 1));
  1340.  
  1341.         } elseif ($cells < 0) {
  1342.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1343.                 array('var' => '$cells',
  1344.                       'was' => $cells,
  1345.                       'expected' => 'greater or equal zero',
  1346.                       'paramnum' => 1));
  1347.         }
  1348.         $this->cellCount = $cells;
  1349.  
  1350.         $this->_updateProgressSize();   // updates the new size of progress bar
  1351.     }
  1352.  
  1353.     /**
  1354.      * Returns cell attributes values.
  1355.      *
  1356.      * Get all cell attributes in a associative array with key-value couple
  1357.      * (by default). Get the attributes as string is also possible.
  1358.      *
  1359.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1360.      *
  1361.      * @return     mixed
  1362.      * @since      2.0.0
  1363.      * @access     public
  1364.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1365.      * @see        setCellAttributes()
  1366.      */
  1367.     function getCellAttributes($asString = false)
  1368.     {
  1369.         if (!is_bool($asString)) {
  1370.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1371.                 array('var' => '$asString',
  1372.                       'was' => gettype($asString),
  1373.                       'expected' => 'boolean',
  1374.                       'paramnum' => 1));
  1375.         }
  1376.  
  1377.         $attr = $this->cell;
  1378.  
  1379.         if ($asString) {
  1380.             return $this->_getAttrString($attr);
  1381.         } else {
  1382.             return $attr;
  1383.         }
  1384.     }
  1385.  
  1386.     /**
  1387.      * Sets cell attributes values.
  1388.      *
  1389.      * Sets cell attributes for all cells (default) or a specific an existing cell.
  1390.      *
  1391.      * Defaults are:
  1392.      *     <ul>
  1393.      *     <li>id             = pcel%01s
  1394.      *     <li>class          = cell
  1395.      *     <li>spacing        = 2
  1396.      *     <li>active-color   = #006600
  1397.      *     <li>inactive-color = #CCCCCC
  1398.      *     <li>font-family    = Courier, Verdana
  1399.      *     <li>font-size      = lowest value from cell width, cell height, and font size
  1400.      *     <li>color          = #000000
  1401.      *     <li>background-color    = #FFFFFF
  1402.      *     <li>background-image    = none
  1403.      *     <li>background-repeat   = no-repeat
  1404.      *     <li>background-position = top left
  1405.      *     <li>Horizontal Bar :
  1406.      *         <ul>
  1407.      *         <li>width      = 15
  1408.      *         <li>height     = 20
  1409.      *         </ul>
  1410.      *     <li>Vertical Bar :
  1411.      *         <ul>
  1412.      *         <li>width      = 20
  1413.      *         <li>height     = 15
  1414.      *         </ul>
  1415.      *     </ul>
  1416.      *
  1417.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1418.      * @param      int       $cell          (optional) Cell index
  1419.      *
  1420.      * @return     void
  1421.      * @since      2.0.0
  1422.      * @access     public
  1423.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1424.      * @see        getCellAttributes()
  1425.      */
  1426.     function setCellAttributes($attributes, $cell = null)
  1427.     {
  1428.         if (!is_null($cell)) {
  1429.             if (!is_int($cell)) {
  1430.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1431.                     array('var' => '$cell',
  1432.                           'was' => gettype($cell),
  1433.                           'expected' => 'integer',
  1434.                           'paramnum' => 1));
  1435.  
  1436.             } elseif ($cell < 0) {
  1437.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1438.                     array('var' => '$cell',
  1439.                           'was' => $cell,
  1440.                           'expected' => 'positive',
  1441.                           'paramnum' => 1));
  1442.  
  1443.             } elseif ($cell > $this->cellCount) {
  1444.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1445.                     array('var' => '$cell',
  1446.                           'was' => $cell,
  1447.                           'expected' => 'less or equal '.$this->cellCount,
  1448.                           'paramnum' => 1));
  1449.             }
  1450.  
  1451.             $this->_updateAttrArray($this->cell[$cell], $this->_parseAttributes($attributes));
  1452.         } else {
  1453.             $this->_updateAttrArray($this->cell, $this->_parseAttributes($attributes));
  1454.         }
  1455.  
  1456.         $font_size   = $this->cell['font-size'];
  1457.         $cell_width  = $this->cell['width'];
  1458.         $cell_height = $this->cell['height'];
  1459.         $margin = ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) ? 0 : 3;
  1460.  
  1461.         $font_size = min(min($cell_width, $cell_height) - $margin, $font_size);
  1462.         $this->cell['font-size'] = $font_size;
  1463.  
  1464.         $this->_updateProgressSize();   // updates the new size of progress bar
  1465.     }
  1466.  
  1467.     /**
  1468.      * Returns coordinates of each cell for a polygonal progress meter.
  1469.      *
  1470.      * Get array of all cell coordinates (x,y) that define a polygonal
  1471.      * progress meter.
  1472.      * For example, a 3x3 square as: (0,0) for top left corner,
  1473.      * (2,0) for top right corner, (2,2) for bottom right corner, and
  1474.      * (0,2) for bottom left corner.
  1475.      *
  1476.      * @return     array
  1477.      * @since      2.0.0
  1478.      * @access     public
  1479.      * @see        setCellCoordinates()
  1480.      */
  1481.     function getCellCoordinates()
  1482.     {
  1483.         return isset($this->_coordinates) ? $this->_coordinates : array();
  1484.     }
  1485.  
  1486.     /**
  1487.      * Sets coordinates of each cell for a polygonal progress meter.
  1488.      *
  1489.      * A polygonal progress meter is defined by its size (width, height) and its
  1490.      * cells coordinates (array of couple x,y screen coordinates).
  1491.      *
  1492.      * @param      integer   $xgrid     The grid width in cell size
  1493.      * @param      integer   $ygrid     The grid height in cell size
  1494.      * @param      array     $coord     (optional) Coordinates (x,y) in the grid, of each cell
  1495.      *
  1496.      * @return     void
  1497.      * @since      2.0.0
  1498.      * @access     public
  1499.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1500.      * @see        getCellCoordinates()
  1501.      */
  1502.     function setCellCoordinates($xgrid, $ygrid, $coord = array())
  1503.     {
  1504.         if (!is_int($xgrid)) {
  1505.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1506.                 array('var' => '$xgrid',
  1507.                       'was' => gettype($xgrid),
  1508.                       'expected' => 'integer',
  1509.                       'paramnum' => 1));
  1510.  
  1511.         } elseif ($xgrid < 3) {
  1512.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1513.                 array('var' => '$xgrid',
  1514.                       'was' => $xgrid,
  1515.                       'expected' => 'greater than 2',
  1516.                       'paramnum' => 1));
  1517.  
  1518.         } elseif (!is_int($ygrid)) {
  1519.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1520.                 array('var' => '$ygrid',
  1521.                       'was' => gettype($ygrid),
  1522.                       'expected' => 'integer',
  1523.                       'paramnum' => 2));
  1524.  
  1525.         } elseif ($ygrid < 3) {
  1526.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1527.                 array('var' => '$ygrid',
  1528.                       'was' => $ygrid,
  1529.                       'expected' => 'greater than 2',
  1530.                       'paramnum' => 2));
  1531.  
  1532.         } elseif (!is_array($coord)) {
  1533.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1534.                 array('var' => '$coord',
  1535.                       'was' => gettype($coord),
  1536.                       'expected' => 'array',
  1537.                       'paramnum' => 3));
  1538.         }
  1539.  
  1540.         if (count($coord) == 0) {
  1541.             // Computes all coordinates of a standard polygon (square or rectangle)
  1542.             $coord = $this->_computeCoordinates($xgrid, $ygrid);
  1543.         } else {
  1544.             foreach ($coord as $id => $pos) {
  1545.                 if (!is_array($pos)) {
  1546.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1547.                         array('var' => '$coord[,$pos]',
  1548.                               'was' => gettype($pos),
  1549.                               'expected' => 'array',
  1550.                               'paramnum' => 3));
  1551.                 }
  1552.                 if ($pos[0] >= $ygrid) {
  1553.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1554.                         array('var' => '$pos[0]',
  1555.                               'was' => $pos[0],
  1556.                               'expected' => 'coordinate less than grid height',
  1557.                               'paramnum' => 2));
  1558.                 }
  1559.                 if ($pos[1] >= $xgrid) {
  1560.                     return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1561.                         array('var' => '$pos[1]',
  1562.                               'was' => $pos[1],
  1563.                               'expected' => 'coordinate less than grid width',
  1564.                               'paramnum' => 1));
  1565.                 }
  1566.             }
  1567.         }
  1568.         $this->_coordinates = $coord;
  1569.         $this->_xgrid = $xgrid;
  1570.         $this->_ygrid = $ygrid;
  1571.  
  1572.         // auto-compute cell count
  1573.         $this->cellCount = count($coord);
  1574.  
  1575.         $this->_updateProgressSize();   // updates the new size of progress bar
  1576.     }
  1577.  
  1578.     /**
  1579.      * Returns progress bar's border attributes values.
  1580.      *
  1581.      * Get all border attributes in a associative array with key-value couple
  1582.      * (by default). Get the attributes as string is also possible.
  1583.      *
  1584.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1585.      *
  1586.      * @return     mixed
  1587.      * @since      2.0.0
  1588.      * @access     public
  1589.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1590.      * @see        setBorderAttributes()
  1591.      */
  1592.     function getBorderAttributes($asString = false)
  1593.     {
  1594.         if (!is_bool($asString)) {
  1595.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1596.                 array('var' => '$asString',
  1597.                       'was' => gettype($asString),
  1598.                       'expected' => 'boolean',
  1599.                       'paramnum' => 1));
  1600.         }
  1601.  
  1602.         $attr = $this->border;
  1603.  
  1604.         if ($asString) {
  1605.             return $this->_getAttrString($attr);
  1606.         } else {
  1607.             return $attr;
  1608.         }
  1609.     }
  1610.  
  1611.     /**
  1612.      * Sets the progress bar's border attributes.
  1613.      *
  1614.      * Defines all border attributes (color, size, ...) a progress bar
  1615.      * (only horizontal or vertical) can handle.
  1616.      *
  1617.      * Defaults are:
  1618.      * <ul>
  1619.      * <li>class   = progressBorder%s
  1620.      * <li>width   = 0
  1621.      * <li>style   = solid
  1622.      * <li>color   = #000000
  1623.      * </ul>
  1624.      *
  1625.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1626.      *
  1627.      * @return     void
  1628.      * @since      2.0.0
  1629.      * @access     public
  1630.      * @see        getBorderAttributes()
  1631.      */
  1632.     function setBorderAttributes($attributes)
  1633.     {
  1634.         $this->_updateAttrArray($this->border, $this->_parseAttributes($attributes));
  1635.  
  1636.         $this->_updateProgressSize();   // updates the new size of progress bar
  1637.     }
  1638.  
  1639.     /**
  1640.      * Returns frame attributes values.
  1641.      *
  1642.      * Get all frame attributes in a associative array with key-value couple
  1643.      * (by default). Get the attributes as string is also possible.
  1644.      *
  1645.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1646.      *
  1647.      * @return     mixed
  1648.      * @since      2.0.0
  1649.      * @access     public
  1650.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1651.      * @see        setFrameAttributes()
  1652.      */
  1653.     function getFrameAttributes($asString = false)
  1654.     {
  1655.         if (!is_bool($asString)) {
  1656.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1657.                 array('var' => '$asString',
  1658.                       'was' => gettype($asString),
  1659.                       'expected' => 'boolean',
  1660.                       'paramnum' => 1));
  1661.         }
  1662.  
  1663.         $attr = $this->frame;
  1664.  
  1665.         if ($asString) {
  1666.             return $this->_getAttrString($attr);
  1667.         } else {
  1668.             return $attr;
  1669.         }
  1670.     }
  1671.  
  1672.     /**
  1673.      * Sets the progress meter frame attributes.
  1674.      *
  1675.      * Allows to build a customisable frame (color, size) around the progress meter.
  1676.      *
  1677.      * Defaults are:
  1678.      * <ul>
  1679.      * <li>show          = true
  1680.      * <li>left          = 200
  1681.      * <li>top           = 100
  1682.      * <li>width         = 320
  1683.      * <li>height        = 90
  1684.      * <li>color         = #C0C0C0
  1685.      * <li>border-width  = 2
  1686.      * <li>border-style  = solid
  1687.      * <li>border-color  = #DFDFDF #404040 #404040 #DFDFDF
  1688.      * </ul>
  1689.      *
  1690.      * @param      null|array     $attributes    (optional) hash of style parameters
  1691.      *
  1692.      * @return     void
  1693.      * @since      2.0.0
  1694.      * @access     public
  1695.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT,
  1696.      *             HTML_PROGRESS2_ERROR_INVALID_OPTION
  1697.      */
  1698.     function setFrameAttributes($attributes = array())
  1699.     {
  1700.         if (!is_null($attributes) && !is_array($attributes)) {
  1701.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1702.                 array('var' => '$attributes',
  1703.                       'was' => gettype($attributes),
  1704.                       'expected' => 'array',
  1705.                       'paramnum' => 1));
  1706.         }
  1707.  
  1708.         $default = array(
  1709.             'show' => true,
  1710.             'left' => 200,
  1711.             'top' => 100,
  1712.             'width' => 320,
  1713.             'height' => 90,
  1714.             'color' => '#C0C0C0',
  1715.             'border-width' => 2,
  1716.             'border-style' => 'solid',
  1717.             'border-color' => '#DFDFDF #404040 #404040 #DFDFDF'
  1718.         );
  1719.         $allowed_options = array_keys($default);
  1720.  
  1721.         $options = array_merge($default, $attributes);
  1722.  
  1723.         foreach($options as $prop => $val) {
  1724.             if (in_array($prop, $allowed_options)) {
  1725.                 $this->frame[$prop] = $val;
  1726.             } else {
  1727.                 $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_OPTION, 'warning',
  1728.                     array('element' => 'frame', 'prop' => $prop)
  1729.                     );
  1730.             }
  1731.         }
  1732.     }
  1733.  
  1734.     /**
  1735.      * Returns attributes values of an existing label.
  1736.      *
  1737.      * Get all attributes of an existing label identified by $name argument.
  1738.      * This identifier must be the same as the one given to addLabel() method.
  1739.      * Return attributes values in a associative array with key-value couple
  1740.      * (by default). Get the attributes as string is also possible.
  1741.      *
  1742.      * @param      string    $name          progress label id.
  1743.      * @param      bool      $asString      (optional) whether to return the attributes as string
  1744.      *
  1745.      * @return     mixed
  1746.      * @since      2.0.0
  1747.      * @access     public
  1748.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1749.      * @see        setLabelAttributes()
  1750.      */
  1751.     function getLabelAttributes($name, $asString = false)
  1752.     {
  1753.         if (!isset($this->label[$name])) {
  1754.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1755.                 array('var' => '$name',
  1756.                       'was' => 'undefined',
  1757.                       'expected' => "label '$name' exists",
  1758.                       'paramnum' => 1));
  1759.  
  1760.         } elseif (!is_bool($asString)) {
  1761.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1762.                 array('var' => '$asString',
  1763.                       'was' => gettype($asString),
  1764.                       'expected' => 'boolean',
  1765.                       'paramnum' => 2));
  1766.         }
  1767.  
  1768.         $attr = $this->label[$name];
  1769.  
  1770.         if ($asString) {
  1771.             return $this->_getAttrString($attr);
  1772.         } else {
  1773.             return $attr;
  1774.         }
  1775.     }
  1776.  
  1777.     /**
  1778.      * Sets attributes values of an existing label.
  1779.      *
  1780.      * Defines attributes (font, color, size, alignement ...) of an existing label.
  1781.      * Whether an attribute is not specified, previous or default value
  1782.      * is used instead.
  1783.      *
  1784.      * Defaults are:
  1785.      * <ul>
  1786.      * <li>class             = progressPercentLabel%s
  1787.      * <li>width             = 50
  1788.      * <li>height            = 0
  1789.      * <li>font-size         = 11
  1790.      * <li>font-family       = Verdana, Tahoma, Arial
  1791.      * <li>font-weight       = normal
  1792.      * <li>color             = #000000
  1793.      * <li>background-color  = transparent
  1794.      * <li>align             = right
  1795.      * <li>valign            = right
  1796.      * </ul>
  1797.      *
  1798.      * @param      string    $name          progress label id.
  1799.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  1800.      *
  1801.      * @return     void
  1802.      * @since      2.0.0
  1803.      * @access     public
  1804.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1805.      * @see        getLabelAttributes(), addLabel()
  1806.      */
  1807.     function setLabelAttributes($name, $attributes)
  1808.     {
  1809.         if (!isset($this->label[$name])) {
  1810.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1811.                 array('var' => '$name',
  1812.                       'was' => "label '$name' undefined",
  1813.                       'expected' => 'label already exists',
  1814.                       'paramnum' => 1));
  1815.         }
  1816.  
  1817.         $this->_updateAttrArray($this->label[$name], $this->_parseAttributes($attributes));
  1818.  
  1819.         if ($this->label[$name]['type'] == HTML_PROGRESS2_LABEL_TEXT) {
  1820.             if ($this->_status != 'new') {
  1821.                 $this->_changeLabelText($name, $this->label[$name]['value']);
  1822.             }
  1823.         }
  1824.     }
  1825.  
  1826.     /**
  1827.      * Add a new label to the progress meter.
  1828.      *
  1829.      * Defines a new label identifier choosen between five categories:
  1830.      * <ul>
  1831.      * <li>HTML_PROGRESS2_LABEL_TEXT constant if you want a simple text zone
  1832.      * <li>HTML_PROGRESS2_LABEL_BUTTON constant if you want a form button
  1833.      * <li>HTML_PROGRESS2_LABEL_STEP constant if you want a step resume progress
  1834.      * <li>HTML_PROGRESS2_LABEL_PERCENT constant if you want current progress value
  1835.      * <li>HTML_PROGRESS2_LABEL_CROSSBAR constant if you want a little javascript animation
  1836.      * </ul>
  1837.      *
  1838.      * @param      string    $type          Label type (text,button,step,percent,crossbar)
  1839.      * @param      string    $name          Label name
  1840.      * @param      string    $value         (optional) default label value
  1841.      *
  1842.      * @return     void
  1843.      * @since      2.0.0
  1844.      * @access     public
  1845.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1846.      * @see        setLabelAttributes(), removeLabel()
  1847.      */
  1848.     function addLabel($type, $name, $value = ' ')
  1849.     {
  1850.         if (($type != HTML_PROGRESS2_LABEL_TEXT) &&
  1851.             ($type != HTML_PROGRESS2_LABEL_BUTTON) &&
  1852.             ($type != HTML_PROGRESS2_LABEL_STEP) &&
  1853.             ($type != HTML_PROGRESS2_LABEL_PERCENT) &&
  1854.             ($type != HTML_PROGRESS2_LABEL_CROSSBAR)) {
  1855.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1856.                 array('var' => '$type',
  1857.                       'was' => $type,
  1858.                       'expected' => 'HTML_PROGRESS2_LABEL_* constant value',
  1859.                       'paramnum' => 1));
  1860.  
  1861.         } elseif (!is_string($name)) {
  1862.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1863.                 array('var' => '$name',
  1864.                       'was' => gettype($name),
  1865.                       'expected' => 'string',
  1866.                       'paramnum' => 2));
  1867.  
  1868.         } elseif (isset($this->label[$name])) {
  1869.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  1870.                 array('var' => '$name',
  1871.                       'was' => 'label already exists',
  1872.                       'expected' => "label '$name' undefined",
  1873.                       'paramnum' => 2));
  1874.  
  1875.         } elseif (!is_string($value)) {
  1876.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1877.                 array('var' => '$value',
  1878.                       'was' => gettype($value),
  1879.                       'expected' => 'string',
  1880.                       'paramnum' => 3));
  1881.         }
  1882.  
  1883.         switch($type) {
  1884.         case HTML_PROGRESS2_LABEL_TEXT:
  1885.             $this->label[$name] = array(
  1886.                 'type' => $type,
  1887.                 'value' => $value,
  1888.                 'left' => 5,
  1889.                 'top' => 5,
  1890.                 'width' => 0,
  1891.                 'height' => 0,
  1892.                 'align' => 'left',
  1893.                 'valign' => 'top',
  1894.                 'background-color' => 'transparent',
  1895.                 'font-size' => 11,
  1896.                 'font-family' => 'Verdana, Tahoma, Arial',
  1897.                 'font-weight' => 'normal',
  1898.                 'color' => '#000000',
  1899.                 'class' => 'progressTextLabel%s'
  1900.             );
  1901.             break;
  1902.         case HTML_PROGRESS2_LABEL_BUTTON:
  1903.             $this->label[$name] = array(
  1904.                 'type' => $type,
  1905.                 'value' => $value,
  1906.                 'action' => '',
  1907.                 'target' => 'self',
  1908.                 'left' => 0,
  1909.                 'top' => 5,
  1910.                 'width' => 0,
  1911.                 'height' => 0,
  1912.                 'align' => 'center',
  1913.                 'valign' => 'bottom',
  1914.                 'background-color' => 'transparent',
  1915.                 'font-size' => 11,
  1916.                 'font-family' => 'Verdana, Tahoma, Arial',
  1917.                 'font-weight' => 'normal',
  1918.                 'color' => '#000000',
  1919.                 'class' => 'progressButtonLabel%s'
  1920.             );
  1921.             break;
  1922.         case HTML_PROGRESS2_LABEL_STEP:
  1923.             $this->label[$name] = array(
  1924.                 'type' => $type,
  1925.                 'value' => $value,
  1926.                 'left' => 5,
  1927.                 'top' => 5,
  1928.                 'width' => 165,
  1929.                 'height' => 0,
  1930.                 'align' => 'right',
  1931.                 'valign' => 'top',
  1932.                 'background-color' => 'transparent',
  1933.                 'font-size' => 11,
  1934.                 'font-family' => 'Verdana, Tahoma, Arial',
  1935.                 'font-weight' => 'normal',
  1936.                 'color' => '#000000',
  1937.                 'class' => 'progressStepLabel%s'
  1938.             );
  1939.             break;
  1940.         case HTML_PROGRESS2_LABEL_PERCENT:
  1941.             $this->label[$name] = array(
  1942.                 'type' => $type,
  1943.                 'value' => $value,
  1944.                 'left' => 5,
  1945.                 'top' => 5,
  1946.                 'width' => 50,
  1947.                 'height' => 0,
  1948.                 'align' => 'right',
  1949.                 'valign' => 'right',
  1950.                 'background-color' => 'transparent',
  1951.                 'font-size' => 11,
  1952.                 'font-family' => 'Verdana, Tahoma, Arial',
  1953.                 'font-weight' => 'normal',
  1954.                 'color' => '#000000',
  1955.                 'class' => 'progressPercentLabel%s'
  1956.             );
  1957.             break;
  1958.         case HTML_PROGRESS2_LABEL_CROSSBAR:
  1959.             $this->label[$name] = array(
  1960.                 'type' => $type,
  1961.                 'value' => $value,
  1962.                 'left' => 5,
  1963.                 'top' => 5,
  1964.                 'width' => 20,
  1965.                 'height' => 0,
  1966.                 'align' => 'center',
  1967.                 'valign' => 'top',
  1968.                 'background-color' => 'transparent',
  1969.                 'font-size' => 11,
  1970.                 'font-family' => 'Verdana, Tahoma, Arial',
  1971.                 'font-weight' => 'normal',
  1972.                 'color' => '#000000',
  1973.                 'class' => 'progressCrossbarLabel%s'
  1974.             );
  1975.             break;
  1976.         }
  1977.     }
  1978.  
  1979.     /**
  1980.      * Removes a label to the progress meter.
  1981.      *
  1982.      * The label identifier must exists or it cannot be remove. This is the same
  1983.      * identifier as the one given to addLabel() method.
  1984.      *
  1985.      * @param      string    $name          Label name
  1986.      *
  1987.      * @return     void
  1988.      * @since      2.0.0
  1989.      * @access     public
  1990.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  1991.      * @see        addLabel()
  1992.      */
  1993.     function removeLabel($name)
  1994.     {
  1995.         if (!is_string($name)) {
  1996.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  1997.                 array('var' => '$name',
  1998.                       'was' => gettype($name),
  1999.                       'expected' => 'string',
  2000.                       'paramnum' => 1));
  2001.  
  2002.         } elseif (!isset($this->label[$name])) {
  2003.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'notice',
  2004.                 array('var' => '$name',
  2005.                       'was' => 'label does not exists',
  2006.                       'expected' => "label '$name' defined",
  2007.                       'paramnum' => 1));
  2008.  
  2009.         }
  2010.  
  2011.         unset($this->label[$name]);
  2012.     }
  2013.  
  2014.     /**
  2015.      * Returns the progress background attributes values.
  2016.      *
  2017.      * Get all background attributes in a associative array with key-value couple
  2018.      * (by default). Get the attributes as string is also possible.
  2019.      *
  2020.      * @param      bool      $asString      (optional) whether to return the attributes as string
  2021.      *
  2022.      * @return     mixed
  2023.      * @since      2.0.0
  2024.      * @access     public
  2025.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2026.      * @see        setProgressAttributes()
  2027.      */
  2028.     function getProgressAttributes($asString = false)
  2029.     {
  2030.         if (!is_bool($asString)) {
  2031.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2032.                 array('var' => '$asString',
  2033.                       'was' => gettype($asString),
  2034.                       'expected' => 'boolean',
  2035.                       'paramnum' => 1));
  2036.         }
  2037.  
  2038.         $attr = $this->_progress;
  2039.  
  2040.         if ($asString) {
  2041.             return $this->_getAttrString($attr);
  2042.         } else {
  2043.             return $attr;
  2044.         }
  2045.     }
  2046.  
  2047.     /**
  2048.      * Sets the progress background attributes values.
  2049.      *
  2050.      * Background attributes are color and size, with default values:
  2051.      * <ul>
  2052.      * <li>background-color    = #FFFFFF
  2053.      * <li>background-image    = none
  2054.      * <li>background-repeat   = no-repeat
  2055.      * <li>background-position = top left
  2056.      * <li>Horizontal Bar :
  2057.      *     <ul>
  2058.      *     <li>width         = (cell_count * (cell_width + cell_spacing)) + cell_spacing
  2059.      *     <li>height        = cell_height + (2 * cell_spacing)
  2060.      *     </ul>
  2061.      * <li>Vertical Bar :
  2062.      *     <ul>
  2063.      *     <li>width         = cell_width + (2 * cell_spacing)
  2064.      *     <li>height        = (cell_count * (cell_height + cell_spacing)) + cell_spacing
  2065.      *     </ul>
  2066.      * </ul>
  2067.      *
  2068.      * @param      mixed     $attributes    Associative array or string of HTML tag attributes
  2069.      *
  2070.      * @return     void
  2071.      * @since      2.0.0
  2072.      * @access     public
  2073.      * @see        getProgressAttributes()
  2074.      */
  2075.     function setProgressAttributes($attributes)
  2076.     {
  2077.         $this->_updateAttrArray($this->_progress, $this->_parseAttributes($attributes));
  2078.     }
  2079.  
  2080.     /**
  2081.      * Returns javascript progress meter handler.
  2082.      *
  2083.      * Get the javascript URL or inline code that will handle the progress meter
  2084.      * refresh.
  2085.      *
  2086.      * @param      boolean   (optional) html output with script tags or just raw data
  2087.      *
  2088.      * @return     string
  2089.      * @since      2.0.0
  2090.      * @access     public
  2091.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2092.      * @see        setScript()
  2093.      */
  2094.     function getScript($raw = true)
  2095.     {
  2096.         if (!is_bool($raw)) {
  2097.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2098.                 array('var' => '$raw',
  2099.                       'was' => gettype($raw),
  2100.                       'expected' => 'boolean',
  2101.                       'paramnum' => 1));
  2102.         }
  2103.  
  2104.         if (!is_null($this->script)) {
  2105.  
  2106.             if ($raw) {
  2107.                 $js = $this->script;   // URL to the linked Progress JavaScript
  2108.             } else {
  2109.                 $js = '<script type="text/javascript" src="' . $this->script
  2110.                     . '"></script>' . PHP_EOL;
  2111.             }
  2112.             return $js;
  2113.         }
  2114.  
  2115.         $js = <<< JS
  2116.  
  2117. function setProgress(pIdent, pValue, pDeterminate, pCellCount)
  2118. {
  2119.     if (pValue == pDeterminate) {
  2120.         for (i=0; i < pCellCount; i++) {
  2121.             showCell(i, pIdent, 'hidden');
  2122.         }
  2123.     }
  2124.     if ((pDeterminate > 0) && (pValue > 0)) {
  2125.         i = (pValue - 1) % pCellCount;
  2126.         showCell(i, pIdent, 'visible');
  2127.     } else {
  2128.         for (i = pValue - 1; i >=0; i--) {
  2129.             showCell(i, pIdent, 'visible');
  2130.         }
  2131.     }
  2132. }
  2133.  
  2134. function showCell(pCell, pIdent, pVisibility)
  2135. {
  2136.     name = '%progressCell%' + pCell + 'A' + pIdent;
  2137.     document.getElementById(name).style.visibility = pVisibility;
  2138. }
  2139.  
  2140. function hideProgress(pIdent, pCellCount)
  2141. {
  2142.     name = 'tfrm' + pIdent;
  2143.     document.getElementById(name).style.visibility = 'hidden';
  2144.     for (i = 0; i < pCellCount; i++) {
  2145.         showCell(i, pIdent, 'hidden');
  2146.     }
  2147. }
  2148.  
  2149. function setLabelText(pIdent, pName, pText)
  2150. {
  2151.     name = 'plbl' + pName + pIdent;
  2152.     document.getElementById(name).firstChild.nodeValue = pText;
  2153. }
  2154.  
  2155. function setElementStyle(pPrefix, pName, pIdent, pStyles)
  2156. {
  2157.     name = pPrefix + pName + pIdent;
  2158.     styles = pStyles.split(';');
  2159.     styles.pop();
  2160.     for (i = 0; i < styles.length; i++)
  2161.     {
  2162.         s = styles[i].split(':');
  2163.         c = 'document.getElementById(name).style.' + s[0] + '="' + s[1] + '"';
  2164.         eval(c);
  2165.     }
  2166. }
  2167.  
  2168. function setRotaryCross(pIdent, pName)
  2169. {
  2170.     name = 'plbl' + pName + pIdent;
  2171.     cross = document.getElementById(name).firstChild.nodeValue;
  2172.     switch(cross) {
  2173.         case "--": cross = "\\\\"; break;
  2174.         case "\\\\": cross = "|"; break;
  2175.         case "|": cross = "/"; break;
  2176.         default: cross = "--"; break;
  2177.     }
  2178.     document.getElementById(name).firstChild.nodeValue = cross;
  2179. }
  2180.  
  2181. JS;
  2182.         $cellAttr = $this->getCellAttributes();
  2183.         $attr = trim(sprintf($cellAttr['id'], '   '));
  2184.         $js = str_replace('%progressCell%', $attr, $js);
  2185.  
  2186.         if ($raw !== true) {
  2187.             $js = '<script type="text/javascript">' . PHP_EOL
  2188.                 . '//<![CDATA[' . $js . '//]]>'     . PHP_EOL
  2189.                 . '</script>'                       . PHP_EOL;
  2190.         }
  2191.         return $js;
  2192.     }
  2193.  
  2194.     /**
  2195.      * Sets the javascript progress meter handler.
  2196.      *
  2197.      * Defines the javascript source (URL or inline code) that will handle
  2198.      * the progress meter refresh.
  2199.      *
  2200.      * @param      string    $url           URL to the linked Progress JavaScript
  2201.      *
  2202.      * @return     void
  2203.      * @since      2.0.0
  2204.      * @access     public
  2205.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2206.      * @see        getScript()
  2207.      */
  2208.     function setScript($url)
  2209.     {
  2210.         if (!is_null($url)) {
  2211.             if (!is_string($url)) {
  2212.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2213.                     array('var' => '$url',
  2214.                           'was' => gettype($url),
  2215.                           'expected' => 'string',
  2216.                           'paramnum' => 1));
  2217.  
  2218.             } elseif (!is_file($url) || $url == '.' || $url == '..') {
  2219.                 return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2220.                     array('var' => '$url',
  2221.                           'was' => $url.' file does not exists',
  2222.                           'expected' => 'javascript file exists',
  2223.                           'paramnum' => 1));
  2224.             }
  2225.         }
  2226.  
  2227.         /*
  2228.          - since version 0.5.0,
  2229.          - default javascript code comes from getScript() method
  2230.          - but may be overrided by external file.
  2231.         */
  2232.         $this->script = $url;
  2233.     }
  2234.  
  2235.     /**
  2236.      * Draw all circle segment pictures.
  2237.      *
  2238.      * This function build/prepare all circle segment PNG pictures that will be
  2239.      * send to browser output. Requires PEAR::Image_Color and PHP:gd extension.
  2240.      *
  2241.      * @param      string    $dir           (optional) Directory where pictures should be created
  2242.      * @param      string    $fileMask      (optional) sprintf format for pictures filename
  2243.      *
  2244.      * @return     array
  2245.      * @since      2.0.0
  2246.      * @access     public
  2247.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2248.      * @see        setCellAttributes()
  2249.      */
  2250.     function drawCircleSegments($dir = '.', $fileMask = 'c%s.png')
  2251.     {
  2252.         if (!is_dir($dir)) {
  2253.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2254.                 array('var' => '$dir',
  2255.                       'was' => $dir,
  2256.                       'expected' => 'directory exists',
  2257.                       'paramnum' => 1));
  2258.         }
  2259.  
  2260.         include_once 'Image/Color.php';
  2261.  
  2262.         $cellAttr  = $this->getCellAttributes();
  2263.         $w = $cellAttr['width'];
  2264.         $h = $cellAttr['height'];
  2265.         $s = $cellAttr['spacing'];
  2266.         $c = intval(360 / $this->cellCount);
  2267.         if (fmod($w,2) == 0) {
  2268.             $cx = floor($w / 2) - 0.5;
  2269.         } else {
  2270.             $cx = floor($w / 2);
  2271.         }
  2272.         if (fmod($h,2) == 0) {
  2273.             $cy = floor($h / 2) - 0.5;
  2274.         } else {
  2275.             $cy = floor($h / 2);
  2276.         }
  2277.  
  2278.         $image = imagecreate($w, $h);
  2279.  
  2280.         $bg     = Image_Color::allocateColor($image,$cellAttr['background-color']);
  2281.         $colorA = Image_Color::allocateColor($image,$cellAttr['active-color']);
  2282.         $colorI = Image_Color::allocateColor($image,$cellAttr['inactive-color']);
  2283.  
  2284.         imagefilledarc($image, $cx, $cy, $w, $h, 0, 360, $colorI, IMG_ARC_EDGED);
  2285.         $filename = $dir . DIRECTORY_SEPARATOR . sprintf($fileMask,0);
  2286.         imagepng($image, $filename);
  2287.         $this->setCellAttributes(array('background-image' => $filename),0);
  2288.  
  2289.         for ($i = 0; $i < $this->cellCount; $i++) {
  2290.             if ($this->fillWay == 'natural') {
  2291.                 $sA = $i*$c;
  2292.                 $eA = ($i+1)*$c;
  2293.                 $sI = ($i+1)*$c;
  2294.                 $eI = 360;
  2295.             } else {
  2296.                 $sA = 360-(($i+1)*$c);
  2297.                 $eA = 360-($i*$c);
  2298.                 $sI = 0;
  2299.                 $eI = 360-(($i+1)*$c);
  2300.             }
  2301.             if ($s > 0) {
  2302.                 imagefilledarc($image, $cx, $cy, $w, $h, 0, $sA, $colorI, IMG_ARC_EDGED);
  2303.             }
  2304.             imagefilledarc($image, $cx, $cy, $w, $h, $sA, $eA, $colorA, IMG_ARC_EDGED);
  2305.             imagefilledarc($image, $cx, $cy, $w, $h, $sI, $eI, $colorI, IMG_ARC_EDGED);
  2306.             $filename = $dir . DIRECTORY_SEPARATOR . sprintf($fileMask,$i+1);
  2307.             imagepng($image, $filename);
  2308.  
  2309.             $this->setCellAttributes(array('background-image' => $filename),$i+1);
  2310.         }
  2311.         imagedestroy($image);
  2312.     }
  2313.  
  2314.     /**
  2315.      * Returns delay execution of the progress meter.
  2316.      *
  2317.      * Given a delay in process of the progress meter is only necessary
  2318.      * if you need demonstration or also smooth animation.
  2319.      * The default value is zero (no delay).
  2320.      *
  2321.      * @return     integer
  2322.      * @since      2.0.0
  2323.      * @access     public
  2324.      * @see        setAnimSpeed()
  2325.      */
  2326.     function getAnimSpeed()
  2327.     {
  2328.         return $this->animSpeed;
  2329.     }
  2330.  
  2331.     /**
  2332.      * Sets delay execution of the progress meter.
  2333.      *
  2334.      * The delay (in milisecond) cannot exceed 1000 (1 second), that is enough
  2335.      * to smooth an animation. User process should slow down animation and in most
  2336.      * case the default value (zero) will be efficient.
  2337.      *
  2338.      * @param      integer   $delay         Delay in milisecond.
  2339.      *
  2340.      * @return     void
  2341.      * @since      2.0.0
  2342.      * @access     public
  2343.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2344.      * @see        getAnimSpeed()
  2345.      */
  2346.     function setAnimSpeed($delay)
  2347.     {
  2348.         if (!is_int($delay)) {
  2349.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2350.                 array('var' => '$delay',
  2351.                       'was' => gettype($delay),
  2352.                       'expected' => 'integer',
  2353.                       'paramnum' => 1));
  2354.  
  2355.         } elseif ($delay < 0) {
  2356.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2357.                 array('var' => '$delay',
  2358.                       'was' => $delay,
  2359.                       'expected' => 'greater than zero',
  2360.                       'paramnum' => 1));
  2361.  
  2362.         } elseif ($delay > 1000) {
  2363.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'error',
  2364.                 array('var' => '$delay',
  2365.                       'was' => $delay,
  2366.                       'expected' => 'less or equal 1000',
  2367.                       'paramnum' => 1));
  2368.         }
  2369.         $this->animSpeed = $delay;
  2370.     }
  2371.  
  2372.     /**
  2373.      * Returns the cascading style sheet (CSS).
  2374.      *
  2375.      * Get the CSS required to display the progress meter in a HTML document.
  2376.      *
  2377.      * @param      boolean   (optional) html output with script tags or just raw data
  2378.      *
  2379.      * @return     string
  2380.      * @since      2.0.0
  2381.      * @access     public
  2382.      * @throws     HTML_PROGRESS2_ERROR_INVALID_INPUT
  2383.      */
  2384.     function getStyle($raw = true)
  2385.     {
  2386.         if (!is_bool($raw)) {
  2387.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_INPUT, 'exception',
  2388.                 array('var' => '$raw',
  2389.                       'was' => gettype($raw),
  2390.                       'expected' => 'boolean',
  2391.                       'paramnum' => 1));
  2392.         }
  2393.  
  2394.         $tab = $this->_getTab();
  2395.         $progressAttr = $this->getProgressAttributes();
  2396.         $borderAttr = $this->getBorderAttributes();
  2397.         $cellAttr = $this->getCellAttributes();
  2398.  
  2399.         $styles  = '.' . sprintf($borderAttr['class'], $this->ident) . ' {' . PHP_EOL;
  2400.         $styles .= $tab . 'width: '. $progressAttr['width'] .'px;'. PHP_EOL;
  2401.         $styles .= $tab . 'height: '. $progressAttr['height'] .'px;'. PHP_EOL;
  2402.         if ($this->isBorderPainted()) {
  2403.             $styles .= $tab . 'border-width: '. $borderAttr['width'] .'px;'. PHP_EOL;
  2404.             $styles .= $tab . 'border-style: '. $borderAttr['style'] .';'. PHP_EOL;
  2405.             $styles .= $tab . 'border-color: '. $borderAttr['color'] .';'. PHP_EOL;
  2406.         }
  2407.         if ($progressAttr['background-image'] !== 'none') {
  2408.             $styles .= $tab . 'background-image: url('. $progressAttr['background-image'] .');'. PHP_EOL;
  2409.             $styles .= $tab . 'background-repeat: '. $progressAttr['background-repeat'] .';'. PHP_EOL;
  2410.             $styles .= $tab . 'background-position: '. $progressAttr['background-position'] .';'. PHP_EOL;
  2411.         }
  2412.  
  2413.         if ($this->cellCount > 0) {
  2414.             $styles .= $tab . 'background-color: '. $progressAttr['background-color'] .';'. PHP_EOL;
  2415.         } else {
  2416.             $styles .= $tab . 'background-color: '. $cellAttr['inactive-color'] .';'. PHP_EOL;
  2417.         }
  2418.         $styles .= '}'. PHP_EOL . PHP_EOL;
  2419.  
  2420.         foreach($this->label as $name => $data) {
  2421.             $styles .= '.' . sprintf($data['class'], $name . $this->ident). ' {' . PHP_EOL;
  2422.  
  2423.             if ($data['width'] > 0) {
  2424.                 $styles .= $tab . 'width: '. $data['width'] .'px;'. PHP_EOL;
  2425.             }
  2426.             if ($data['height'] > 0) {
  2427.                 $styles .= $tab . 'height: '. $data['height'] .'px;'. PHP_EOL;
  2428.             }
  2429.             $styles .= $tab . 'text-align: '. $data['align'] .';'. PHP_EOL;
  2430.             $styles .= $tab . 'background-color: '. $data['background-color'] .';'. PHP_EOL;
  2431.  
  2432.             $styles .= $tab . 'font-size: '. $data['font-size'] .'px;'. PHP_EOL;
  2433.             $styles .= $tab . 'font-family: '. $data['font-family'] .';'. PHP_EOL;
  2434.             $styles .= $tab . 'font-weight: '. $data['font-weight'] .';'. PHP_EOL;
  2435.             $styles .= $tab . 'color: '. $data['color'] .';'. PHP_EOL;
  2436.             $styles .= '}'. PHP_EOL . PHP_EOL;
  2437.         }
  2438.  
  2439.         $cellClsI = '.' . sprintf($cellAttr['class'], $this->ident) . 'I';
  2440.         $cellClsA = '.' . sprintf($cellAttr['class'], $this->ident) . 'A';
  2441.  
  2442.         $styles .= $cellClsI . ', ' . $cellClsA . ' {' . PHP_EOL;
  2443.         $styles .= $tab . 'width: '. $cellAttr['width'] .'px;'. PHP_EOL;
  2444.         $styles .= $tab . 'height: '. $cellAttr['height'] .'px;'. PHP_EOL;
  2445.         $styles .= $tab . 'font-family: '. $cellAttr['font-family'] .';'. PHP_EOL;
  2446.         $styles .= $tab . 'font-size: '. $cellAttr['font-size'] .'px;'. PHP_EOL;
  2447.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  2448.             $styles .= $tab . 'float: left;'. PHP_EOL;
  2449.         }
  2450.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  2451.             $styles .= $tab . 'float: none;'. PHP_EOL;
  2452.         }
  2453.         $styles .= '}'. PHP_EOL . PHP_EOL;
  2454.  
  2455.         $styles .= $cellClsI . ' {' . PHP_EOL;
  2456.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2457.             $styles .= $tab . 'background-image: url("'. $cellAttr[0]['background-image'] .'");'. PHP_EOL;
  2458.             $styles .= $tab . 'background-repeat: no-repeat;'. PHP_EOL;
  2459.         } else {
  2460.             $styles .= $tab . 'background-color: '. $cellAttr['inactive-color'] .';'. PHP_EOL;
  2461.         }
  2462.         $styles .= '}'. PHP_EOL . PHP_EOL;
  2463.  
  2464.         $styles .= $cellClsA . ' {' . PHP_EOL;
  2465.         if ($cellAttr['background-image'] == 'none') {
  2466.             $styles .= $tab . 'background-color: '. $cellAttr['active-color'] .';'. PHP_EOL;
  2467.         } else {
  2468.             $styles .= $tab . 'background-image: url("'. $cellAttr['background-image'] .'");'. PHP_EOL;
  2469.             if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2470.                 $styles .= $tab . 'background-repeat: no-repeat;'. PHP_EOL;
  2471.             } else {
  2472.                 $styles .= $tab . 'background-repeat: '. $cellAttr['background-repeat'] .';'. PHP_EOL;
  2473.                 $styles .= $tab . 'background-position: '. $cellAttr['background-position'] .';'. PHP_EOL;
  2474.             }
  2475.         }
  2476.         $styles .= $tab . 'visibility: hidden;'. PHP_EOL;
  2477.         $styles .= '}'. PHP_EOL . PHP_EOL;
  2478.  
  2479.         if ($raw !== true) {
  2480.             $styles = '<style type="text/css">' . PHP_EOL
  2481.                     . '<!--'    . PHP_EOL
  2482.                     . $styles   . PHP_EOL
  2483.                     . '// -->'  . PHP_EOL
  2484.                     . '</style>'. PHP_EOL;
  2485.         }
  2486.         return $styles;
  2487.     }
  2488.  
  2489.     /**
  2490.      * Returns the progress meter structure into an array.
  2491.      *
  2492.      * Get all progress meter properties, couple key-value, into a php array.
  2493.      * This structure is read-only, a dump-like information.
  2494.      *
  2495.      * @return     array
  2496.      * @since      2.0.0
  2497.      * @access     public
  2498.      */
  2499.     function toArray()
  2500.     {
  2501.         $structure = array(
  2502.             'id' => $this->ident,
  2503.             'indeterminate' => $this->indeterminate,
  2504.             'borderpainted' => $this->isBorderPainted(),
  2505.             'label' => $this->label,
  2506.             'animspeed' => $this->animSpeed,
  2507.             'orientation' => $this->orientation,
  2508.             'fillway' => $this->fillWay,
  2509.             'cell' => $this->cell,
  2510.             'cellcount' => $this->cellCount,
  2511.             'cellcoord' => $this->getCellCoordinates(),
  2512.             'border' => $this->border,
  2513.             'progress' => $this->_progress,
  2514.             'script' => $this->getScript(),
  2515.             'minimum' => $this->minimum,
  2516.             'maximum' => $this->maximum,
  2517.             'increment' => $this->increment,
  2518.             'value' => $this->value,
  2519.             'percent' => $this->getPercentComplete()
  2520.         );
  2521.         return $structure;
  2522.     }
  2523.  
  2524.     /**
  2525.      * Returns the progress meter structure as HTML.
  2526.      *
  2527.      * Get html code required to display the progress meter in any html document.
  2528.      *
  2529.      * @return     string
  2530.      * @since      2.0.0
  2531.      * @access     public
  2532.      */
  2533.     function toHtml()
  2534.     {
  2535.         $strHtml = '';
  2536.         $tabs = $this->_getTabs();
  2537.         $tab = $this->_getTab();
  2538.         $comment = $this->getComment();
  2539.         $progressAttr = $this->getProgressAttributes();
  2540.         $borderAttr = $this->getBorderAttributes();
  2541.         $cellAttr = $this->getCellAttributes();
  2542.  
  2543.         /**
  2544.          *  Adds a progress meter caption in html code is possible.
  2545.          *  See HTML_Common::setComment() method.
  2546.          */
  2547.         if (strlen($comment) > 0) {
  2548.             $strHtml .= $tabs . "<!-- $comment -->" . PHP_EOL;
  2549.         }
  2550.  
  2551.         //  Start of Top progress meter frame
  2552.         if ($this->frame['show']) {
  2553.             $topshift = $progressAttr['top'];
  2554.             $leftshift = $progressAttr['left'];
  2555.             $border = '';
  2556.             if ($this->frame['border-width'] > 0) {
  2557.                 $border = 'border-width:' . $this->frame['border-width'] . 'px;'
  2558.                         . 'border-style:' . $this->frame['border-style'] . ';'
  2559.                         . 'border-color:' . $this->frame['border-color'] . ';';
  2560.             }
  2561.             if ($progressAttr['position'] == 'relative') {
  2562.                 $_top = $_left = 0;
  2563.             } else {
  2564.                 $_top = $this->frame['top'];
  2565.                 $_left = $this->frame['left'];
  2566.             }
  2567.             $strHtml .= $tabs
  2568.                   .  '<div id="tfrm' . $this->ident . '" style="'
  2569.                   .  'position:' . $progressAttr['position'] . ';'
  2570.                   .  'top:' . $_top . 'px;'
  2571.                   .  'left:' . $_left . 'px;'
  2572.                   .  'width:' . $this->frame['width'] . 'px;'
  2573.                   .  'height:' . $this->frame['height'] . 'px;'
  2574.                   .  $border
  2575.                   .  'background-color:' . $this->frame['color'] . ';">'
  2576.                   .  PHP_EOL;
  2577.  
  2578.         } else {
  2579.             $topshift = $leftshift = 0;
  2580.             $strHtml .= $tabs
  2581.                  .  '<div id="tfrm' . $this->ident . '" style="'
  2582.                  .  'position:' . $progressAttr['position'] . ';'
  2583.                  .  'top:' . $progressAttr['top'] . 'px;'
  2584.                  .  'left:' . $progressAttr['left'] . 'px;'
  2585.                  .  'height:{_heightshift_}px;">'
  2586.                  .  PHP_EOL;
  2587.         }
  2588.  
  2589.         //  Start of progress meter border
  2590.         $strHtml .= $tabs
  2591.                  .  '<div id="pbrd' . $this->ident . '"'
  2592.                  .  ' style="position:absolute;top:{_topshift_}px;left:{_leftshift_}px;"'
  2593.                  .  ' class="' . sprintf($borderAttr['class'], $this->ident) . '">'
  2594.                  .  PHP_EOL;
  2595.  
  2596.         //  Start of progress meter
  2597.         if ($this->cellCount == 0) {
  2598.             $strHtml .= $tabs
  2599.                      .  '<div id="pbar' . $this->ident . '" style="'
  2600.                      .  'width:' . $progressAttr['width'] . 'px;'
  2601.                      .  'height:' . $progressAttr['height'] . 'px;'
  2602.                      .  'background-color:' . $cellAttr['active-color'] . ';">'
  2603.                      .  PHP_EOL;
  2604.         } else {
  2605.             $strHtml .= $tabs
  2606.                      .  '<div id="pbar' . $this->ident . '">'
  2607.                      .  PHP_EOL;
  2608.         }
  2609.  
  2610.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  2611.             $progressHtml = $this->_getProgressHbar_toHtml();
  2612.         }
  2613.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  2614.             $progressHtml = $this->_getProgressVbar_toHtml();
  2615.         }
  2616.         if ($this->orientation == HTML_PROGRESS2_POLYGONAL) {
  2617.             $progressHtml = $this->_getProgressPolygonal_toHtml();
  2618.         }
  2619.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  2620.             $cellAttr = $this->getCellAttributes();
  2621.             if (!isset($cellAttr[0]['background-image']) || !file_exists($cellAttr[0]['background-image'])) {
  2622.                 // creates default circle segments pictures :
  2623.                 // 'c0.png'->0% 'c1.png'->10%, 'c2.png'->20%, ... 'c10.png'->100%
  2624.                 $this->drawCircleSegments();
  2625.             }
  2626.             $progressHtml = $this->_getProgressCircle_toHtml();
  2627.         }
  2628.  
  2629.         $strHtml .= $tabs
  2630.                  .  $progressHtml
  2631.                  .  PHP_EOL;
  2632.  
  2633.         //  Enf of progress meter
  2634.         $strHtml .= $tabs
  2635.                  .  '</div>'
  2636.                  .  PHP_EOL;
  2637.  
  2638.         //  Enf of progress meter border
  2639.         $strHtml .= $tabs
  2640.                  .  '</div>'
  2641.                  .  PHP_EOL;
  2642.  
  2643.         $cyshift = 0;
  2644.         $heightshift = $progressAttr['height'];
  2645.  
  2646.         //  Start of progress meter labels
  2647.         foreach ($this->label as $name => $data) {
  2648.  
  2649.             $align = $data['align'];
  2650.             $width = $data['width'];
  2651.             $height = $data['height'];
  2652.  
  2653.             if ($progressAttr['position'] == 'relative') {
  2654.                 switch ($data['valign']) {
  2655.                     case 'top':
  2656.                         $style_pos = 'top:0;left:{_leftshift_}px;';
  2657.                         if ($data['height'] > 0) {
  2658.                             $topshift = $data['height'];
  2659.                         } else {
  2660.                             $topshift = $progressAttr['height'];
  2661.                         }
  2662.                         $height = $topshift;
  2663.                         $heightshift += $height;
  2664.                         break;
  2665.                     case 'right':
  2666.                         $style_pos = 'top:{_topshift_}px;'
  2667.                                    . 'left:{_rxshift_}px;';
  2668.                         break;
  2669.                     case 'bottom':
  2670.                         $style_pos = 'top:{_cyshift_}px;'
  2671.                                    . 'left:{_leftshift_}px;';
  2672.                         $cyshift = $progressAttr['height'];
  2673.                         if ($data['height'] == 0) {
  2674.                             $height = $progressAttr['height'];
  2675.                         }
  2676.                         $heightshift += $height;
  2677.                         break;
  2678.                     case 'left':
  2679.                         $style_pos = 'top:{_topshift_}px;left:0;';
  2680.                         if ($data['width'] > 0) {
  2681.                             $leftshift = $data['width'];
  2682.                         } else {
  2683.                             $leftshift = $progressAttr['width'];
  2684.                         }
  2685.                         $leftshift += $data['left'];
  2686.                         break;
  2687.                     case 'center':
  2688.                         $style_pos = 'top:{_cyshift_}px;'
  2689.                                    . 'left:{_leftshift_}px;';
  2690.                         $cyshift = intval($progressAttr['height']) / 2;
  2691.                         $width = $progressAttr['width'];
  2692.                         $align = 'center';
  2693.                         break;
  2694.                 }
  2695.                 if ($this->frame['show']) {
  2696.                     $style_pos .= 'margin-top:5px;'
  2697.                                .  'margin-left:5px;';
  2698.                 } else {
  2699.                     $style_pos .= 'margin-top:' . $data['top'] . 'px;'
  2700.                                .  'margin-left:' . $data['left'] . 'px;';
  2701.                 }
  2702.                 if ($width > 0) {
  2703.                     $style_pos .= 'width:' . $width . 'px;';
  2704.                 }
  2705.             } else {
  2706.                 $style_pos = 'top:' . $data['top'] . 'px;'
  2707.                            . 'left:' . $data['left'] . 'px;';
  2708.             }
  2709.             $style_cls = sprintf($data['class'], $name . $this->ident);
  2710.  
  2711.             switch ($data['type']) {
  2712.                 case HTML_PROGRESS2_LABEL_TEXT:
  2713.                     $strHtml .= $tabs
  2714.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2715.                              .  ' style="position:absolute;' . $style_pos . '"'
  2716.                              .  ' class="' . $style_cls . '">'
  2717.                              .  $data['value']
  2718.                              .  '</div>'
  2719.                              .  PHP_EOL;
  2720.                     break;
  2721.                 case HTML_PROGRESS2_LABEL_BUTTON:
  2722.                     $strHtml .= $tabs
  2723.                              .  '<div><input id="plbl' . $name . $this->ident
  2724.                              .  '" type="button" value="' . $data['value']
  2725.                              .  '" style="position:absolute;' . $style_pos
  2726.                              .  '" class="' . $style_cls
  2727.                              .  '" onclick="' . $data['target']
  2728.                              .  '.location.href=\'' . $data['action'] . '\'" />'
  2729.                              .  '</div>'
  2730.                              .  PHP_EOL;
  2731.                     break;
  2732.                 case HTML_PROGRESS2_LABEL_STEP:
  2733.                     $strHtml .= $tabs
  2734.                              .  '<div id="plbl' . $name . $this->ident
  2735.                              .  '" style="position:absolute;' . $style_pos
  2736.                              .  '" class="' . $style_cls . '"> '
  2737.                              .  '</div>'
  2738.                              .  PHP_EOL;
  2739.                     break;
  2740.                 case HTML_PROGRESS2_LABEL_PERCENT:
  2741.                     $strHtml .= $tabs
  2742.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2743.                              .  ' style="position:absolute;' .  $style_pos . '"'
  2744.                              .  ' class="' . $style_cls . '"> '
  2745.                              .  '</div>'
  2746.                              .  PHP_EOL;
  2747.                     break;
  2748.                 case HTML_PROGRESS2_LABEL_CROSSBAR:
  2749.                     $strHtml .= $tabs
  2750.                              .  '<div id="plbl' . $name . $this->ident . '"'
  2751.                              .  ' style="position:absolute;' .  $style_pos . '"'
  2752.                              .  ' class="' . $style_cls . '">'
  2753.                              .  $data['value']
  2754.                              .  '</div>'
  2755.                              .  PHP_EOL;
  2756.                     break;
  2757.             }
  2758.         }
  2759.  
  2760.         //  End of Top progress meter frame
  2761.         $strHtml .= $tabs
  2762.                  .  '</div>'
  2763.                  .  PHP_EOL;
  2764.  
  2765.         $placeHolders = array(
  2766.             '{_leftshift_}', '{_topshift_}', '{_heightshift_}',
  2767.             '{_cyshift_}', '{_rxshift_}'
  2768.         );
  2769.         $htmlElement = array(
  2770.             $leftshift, $topshift, $heightshift,
  2771.             ($topshift + $cyshift), ($leftshift + $progressAttr['width'])
  2772.         );
  2773.         $strHtml = str_replace($placeHolders, $htmlElement, $strHtml);
  2774.  
  2775.         return $strHtml;
  2776.     }
  2777.  
  2778.     /**
  2779.      * Renders the new value of progress meter.
  2780.      *
  2781.      * This method should be used only to display initial state of the progress meter.
  2782.      * Next steps to refresh display must use either moveStep() or moveNext() methods.
  2783.      *
  2784.      * @return     void
  2785.      * @since      2.0.0
  2786.      * @access     public
  2787.      */
  2788.     function display()
  2789.     {
  2790.         $this->_status = 'show';
  2791.         echo $this->toHtml();
  2792.     }
  2793.  
  2794.     /**
  2795.      * Hides the progress meter.
  2796.      *
  2797.      * Once the process is over this method provides a solution
  2798.      * to remove/hide the progress meter of the browser screen.
  2799.      *
  2800.      * @return     void
  2801.      * @since      2.0.0
  2802.      * @access     public
  2803.      */
  2804.     function hide()
  2805.     {
  2806.         $bar = '<script type="text/javascript">'
  2807.              .  'hideProgress("' . $this->ident . '",' . $this->cellCount . ');'
  2808.              .  '</script>';
  2809.  
  2810.         echo $bar . PHP_EOL;
  2811.     }
  2812.  
  2813.     /**
  2814.      * Delay execution.
  2815.      *
  2816.      * The HTML_Progress2::sleep() function delays program execution
  2817.      * for the given number of milliseconds.
  2818.      * This is the default user callback when none are defined.
  2819.      *
  2820.      * NOTE: The function {@link http://www.php.net/manual/en/function.usleep.php}
  2821.      *       did not work on Windows systems until PHP 5.0.0
  2822.      *
  2823.      * @return     void
  2824.      * @since      2.0.0
  2825.      * @access     public
  2826.      * @see        getAnimSpeed(), setAnimSpeed(), process()
  2827.      */
  2828.     function sleep()
  2829.     {
  2830.         // convert delay from milliseconds to microseconds
  2831.         $usecs = $this->animSpeed * 1000;
  2832.  
  2833.         if ((substr(PHP_OS, 0, 3) == 'WIN') && (substr(PHP_VERSION,0,1) < '5') ){
  2834.             for ($i = 0; $i < $usecs; $i++) { }
  2835.         } else {
  2836.             usleep($usecs);
  2837.         }
  2838.     }
  2839.  
  2840.     /**
  2841.      * Sets the user progress callback function.
  2842.      *
  2843.      * The process() function will call the user-callback defined here by this
  2844.      * setProgressHandler() method.
  2845.      *
  2846.      * The user-supplied progress function must return either positive
  2847.      * for a step progression, using moveStep() method,
  2848.      * or NULL for a standard progression, using moveNext() method.
  2849.      *
  2850.      * @param      mixed     $handler       Name of function or a class-method.
  2851.      *
  2852.      * @return     void
  2853.      * @since      2.0.0
  2854.      * @access     public
  2855.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK
  2856.      * @see        process()
  2857.      */
  2858.     function setProgressHandler($handler)
  2859.     {
  2860.         if (!is_callable($handler)) {
  2861.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'warning',
  2862.                 array('var' => '$handler',
  2863.                       'element' => 'valid Class-Method/Function',
  2864.                       'was' => 'callback',
  2865.                       'paramnum' => 1));
  2866.         }
  2867.         $this->_callback = $handler;
  2868.     }
  2869.  
  2870.     /**
  2871.      * Performs the progress user process.
  2872.      *
  2873.      * This function call the user-specified progress function, defined by
  2874.      * setProgressHandler() method. Default callback is the HTML_Progress2::sleep() method.
  2875.      *
  2876.      * @return     mixed
  2877.      * @since      2.0.0
  2878.      * @access     public
  2879.      * @see        sleep(), setProgressHandler()
  2880.      */
  2881.     function process()
  2882.     {
  2883.         if ($this->_callback) {
  2884.             return call_user_func_array($this->_callback, array($this->value, &$this));
  2885.         } else {
  2886.             // when there is no valid user callback then default is to sleep a bit ...
  2887.             $this->sleep();
  2888.         }
  2889.     }
  2890.  
  2891.     /**
  2892.      * Runs the progress meter.
  2893.      *
  2894.      * This function accept both modes: indeterminate and determinate,
  2895.      * and execute all actions defined in the user callback identified by
  2896.      * setProgressHandler() method.
  2897.      *
  2898.      * All observers are also notified of main changes (start, stop meter).
  2899.      *
  2900.      * @return     void
  2901.      * @since      2.0.0
  2902.      * @access     public
  2903.      * @see        process(), setProgressHandler()
  2904.      */
  2905.     function run()
  2906.     {
  2907.         $this->_postNotification('onSubmit', array('handler' => __FUNCTION__, 'value' => $this->getValue()));
  2908.         do {
  2909.             $ret = $this->process();
  2910.             if ($this->getPercentComplete() == 1) {
  2911.                 if ($this->indeterminate) {
  2912.                     $this->setValue(0);
  2913.                 } else {
  2914.                     break;
  2915.                 }
  2916.             }
  2917.             if (is_null($ret)) {
  2918.                 $this->moveNext();
  2919.             } else {
  2920.                 $this->moveStep($ret);
  2921.             }
  2922.         } while(1);
  2923.         $this->_postNotification('onLoad', array('handler' => __FUNCTION__, 'value' => $this->getValue()));
  2924.     }
  2925.  
  2926.     /**
  2927.      * Returns the progress meter identifier.
  2928.      *
  2929.      * Each progress meter has its own identifier. That allows to display more than
  2930.      * only once meter at same time on same page.
  2931.      *
  2932.      * @return     string
  2933.      * @since      2.0.0
  2934.      * @access     public
  2935.      * @see        setIdent()
  2936.      */
  2937.     function getIdent()
  2938.     {
  2939.         return $this->ident;
  2940.     }
  2941.  
  2942.     /**
  2943.      * Sets the progress meter identifier.
  2944.      *
  2945.      * Each progress meter has its own identifier. That allows to display more than
  2946.      * only once meter at same time on same page.
  2947.      * If no identification string is given, then the default identifier will be
  2948.      * six first characters of md5 hash value of the current unix timestamp.
  2949.      *
  2950.      * @param      mixed     $ident         (optional) the new identification string.
  2951.      *
  2952.      * @since      2.0.0
  2953.      * @access     public
  2954.      * @see        getIdent()
  2955.      */
  2956.     function setIdent($ident = null)
  2957.     {
  2958.         if (is_null($ident)) {
  2959.             $this->ident = substr(md5(microtime()), 0, 6);
  2960.         } else {
  2961.             $this->ident = $ident;
  2962.         }
  2963.     }
  2964.  
  2965.     /**
  2966.      * Attachs a new observer.
  2967.      *
  2968.      * Adds a new observer to the Event Dispatcher that will listen
  2969.      * for all messages emitted by this HTML_Progress2 instance.
  2970.      *
  2971.      * @param      mixed     $callback      PHP callback that will act as listener
  2972.      *
  2973.      * @return     void
  2974.      * @since      2.0.0
  2975.      * @access     public
  2976.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK
  2977.      * @see        removeListener()
  2978.      */
  2979.     function addListener($callback)
  2980.     {
  2981.         if (!is_callable($callback)) {
  2982.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'exception',
  2983.                 array('var' => '$callback',
  2984.                       'element' => 'valid Class-Method/Function',
  2985.                       'was' => 'callback',
  2986.                       'paramnum' => 1));
  2987.         }
  2988.  
  2989.         $this->dispatcher =& Event_Dispatcher::getInstance();
  2990.         $this->dispatcher->addObserver($callback);
  2991.         $this->_observerCount++;
  2992.     }
  2993.  
  2994.     /**
  2995.      * Removes a registered observer.
  2996.      *
  2997.      * Detachs a previously registered observer and remove the Event Dispatcher
  2998.      * if there is no more observer registered.
  2999.      *
  3000.      * @param      mixed     $callback      PHP callback that act as listener
  3001.      *
  3002.      * @return     bool                     True if observer was removed, false otherwise
  3003.      * @since      2.0.0
  3004.      * @access     public
  3005.      * @throws     HTML_PROGRESS2_ERROR_INVALID_CALLBACK
  3006.      * @see        addListener()
  3007.      */
  3008.     function removeListener($callback)
  3009.     {
  3010.         if (!is_callable($callback)) {
  3011.             return $this->raiseError(HTML_PROGRESS2_ERROR_INVALID_CALLBACK, 'exception',
  3012.                 array('var' => '$callback',
  3013.                       'element' => 'valid Class-Method/Function',
  3014.                       'was' => 'callback',
  3015.                       'paramnum' => 1));
  3016.         }
  3017.  
  3018.         $result = $this->dispatcher->removeObserver($callback);
  3019.  
  3020.         if ($result) {
  3021.             $this->_observerCount--;
  3022.             if ($this->_observerCount == 0) {
  3023.                 unsset($this->dispatcher);
  3024.             }
  3025.         }
  3026.         return $result;
  3027.     }
  3028.  
  3029.     /**
  3030.      * Refresh the progress meter display.
  3031.      *
  3032.      * @param      integer   $value         new value of the progress meter
  3033.      *
  3034.      * @return     void
  3035.      * @since      2.0.0RC2
  3036.      * @access     private
  3037.      * @see        moveStep(), moveNext()
  3038.      */
  3039.     function _refreshDisplay($value)
  3040.     {
  3041.         static $determinate;
  3042.  
  3043.         foreach($this->label as $name => $data) {
  3044.             switch($data['type']) {
  3045.             case HTML_PROGRESS2_LABEL_STEP:
  3046.                 if (!$this->indeterminate) {
  3047.                     $this->_changeLabelText($name, intval(ceil($value / $this->increment))
  3048.                                                  . '/'
  3049.                                                  . intval(ceil($this->maximum / $this->increment))
  3050.                     );
  3051.                 }
  3052.                 break;
  3053.             case HTML_PROGRESS2_LABEL_PERCENT:
  3054.                 if (!$this->indeterminate) {
  3055.                     $this->_changeLabelText($name, $this->getPercentComplete(false) . '%');
  3056.                 }
  3057.                 break;
  3058.             case HTML_PROGRESS2_LABEL_CROSSBAR:
  3059.                 $this->_changeCrossItem($name);
  3060.                 break;
  3061.             }
  3062.         }
  3063.  
  3064.         $bar  = ob_get_clean();
  3065.  
  3066.         if ($this->cellCount > 0) {
  3067.             $cellAmount = ($this->maximum - $this->minimum) / $this->cellCount;
  3068.  
  3069.             if ($this->indeterminate) {
  3070.                 if (isset($determinate)) {
  3071.                     $determinate++;
  3072.                     $progress = $determinate;
  3073.                 } else {
  3074.                     $progress = $determinate = 1;
  3075.                 }
  3076.             } else {
  3077.                 $progress = ($this->value - $this->minimum) / $cellAmount;
  3078.                 $determinate = 0;
  3079.             }
  3080.  
  3081.             $bar .= '<script type="text/javascript">'
  3082.                  .  'setProgress'
  3083.                  .  '("' . $this->ident . '",'
  3084.                  .  intval($progress) . ',' . $determinate . ',' . $this->cellCount
  3085.                  .  ');'
  3086.                  .  '</script>';
  3087.  
  3088.         } else {
  3089.  
  3090.             $position = $this->_computePosition();
  3091.  
  3092.             $orient = $this->orientation;
  3093.             $cssText = '';
  3094.             if ($orient == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3095.                 if ($this->fillWay == 'reverse') {
  3096.                     $cssText .= 'left:' . $position['left'] . 'px;';
  3097.                 }
  3098.                 $cssText .= 'width:' . $position['width'] . 'px;';
  3099.             }
  3100.             if ($orient == HTML_PROGRESS2_BAR_VERTICAL) {
  3101.                 if ($this->fillWay == 'natural') {
  3102.                     $cssText .= 'top:' . $position['top'] . 'px;';
  3103.                 }
  3104.                 $cssText .= 'height:' . $position['height'] . 'px;';
  3105.             }
  3106.             $bar .= $this->_changeElementStyle('pbar', '', $cssText);
  3107.         }
  3108.         echo $bar . PHP_EOL;
  3109.         ob_start();
  3110.     }
  3111.  
  3112.     /**
  3113.      * Returns a horizontal progress bar structure as HTML.
  3114.      *
  3115.      * @return     string
  3116.      * @since      2.0.0
  3117.      * @access     private
  3118.      */
  3119.     function _getProgressHbar_toHtml()
  3120.     {
  3121.         $tabs = $this->_getTabs();
  3122.         $tab = $this->_getTab();
  3123.         $way_natural = ($this->fillWay == 'natural');
  3124.         $cellAttr = $this->getCellAttributes();
  3125.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3126.         $html = '';
  3127.  
  3128.         if ($way_natural) {
  3129.             // inactive cells first
  3130.             $pos = $cellAttr['spacing'];
  3131.             for ($i = 0; $i < $this->cellCount; $i++) {
  3132.                 $html .= $tabs . $tab
  3133.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3134.                       .  ' class="' . $cellCls . 'I"'
  3135.                       .  ' style="position:absolute;'
  3136.                       .  'left:' . $pos . 'px;'
  3137.                       .  'top:' . $cellAttr['spacing'] . 'px;'
  3138.                       .  '"></div>'
  3139.                       .  PHP_EOL;
  3140.  
  3141.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3142.             }
  3143.             // then active cells
  3144.             $pos = $cellAttr['spacing'];
  3145.             for ($i = 0; $i < $this->cellCount; $i++) {
  3146.                 $html .= $tabs . $tab
  3147.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3148.                       .  ' class="' . $cellCls . 'A"'
  3149.                       .  ' style="position:absolute;'
  3150.                       .  'left:' . $pos . 'px;'
  3151.                       .  'top:' . $cellAttr['spacing'] . 'px;';
  3152.                 if (isset($cellAttr[$i])) {
  3153.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3154.                 }
  3155.                 $html .= '"></div>' . PHP_EOL;
  3156.  
  3157.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3158.             }
  3159.         } else {
  3160.             // inactive cells first
  3161.             $pos = $cellAttr['spacing'];
  3162.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3163.                 $html .= $tabs . $tab
  3164.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3165.                       .  ' class="' . $cellCls . 'I"'
  3166.                       .  ' style="position:absolute;'
  3167.                       .  'left:' . $pos . 'px;'
  3168.                       .  'top:' . $cellAttr['spacing'] . 'px;'
  3169.                       .  '"></div>'
  3170.                       .  PHP_EOL;
  3171.  
  3172.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3173.             }
  3174.             // then active cells
  3175.             $pos = $cellAttr['spacing'];
  3176.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3177.                 $html .= $tabs . $tab
  3178.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3179.                       .  ' class="' . $cellCls . 'A"'
  3180.                       .  ' style="position:absolute;'
  3181.                       .  'left:' . $pos . 'px;'
  3182.                       .  'top:' . $cellAttr['spacing'] . 'px;';
  3183.                 if (isset($cellAttr[$i])) {
  3184.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3185.                 }
  3186.                 $html .= '"></div>' . PHP_EOL;
  3187.  
  3188.                 $pos += ($cellAttr['width'] + $cellAttr['spacing']);
  3189.             }
  3190.         }
  3191.         return $html;
  3192.     }
  3193.  
  3194.     /**
  3195.      * Returns a vertical progress bar structure as HTML.
  3196.      *
  3197.      * @return     string
  3198.      * @since      2.0.0
  3199.      * @access     private
  3200.      */
  3201.     function _getProgressVbar_toHtml()
  3202.     {
  3203.         $tabs = $this->_getTabs();
  3204.         $tab = $this->_getTab();
  3205.         $way_natural = ($this->fillWay == 'natural');
  3206.         $cellAttr = $this->getCellAttributes();
  3207.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3208.         $html = '';
  3209.  
  3210.         if ($way_natural) {
  3211.             // inactive cells first
  3212.             $pos = $cellAttr['spacing'];
  3213.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3214.                 $html .= $tabs . $tab
  3215.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3216.                       .  ' class="' . $cellCls . 'I"'
  3217.                       .  ' style="position:absolute;'
  3218.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3219.                       .  'top:' . $pos . 'px;'
  3220.                       .  '"></div>'
  3221.                       .  PHP_EOL;
  3222.  
  3223.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3224.             }
  3225.             // then active cells
  3226.             $pos = $cellAttr['spacing'];
  3227.             for ($i = $this->cellCount - 1; $i >= 0; $i--) {
  3228.                 $html .= $tabs . $tab
  3229.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3230.                       .  ' class="' . $cellCls . 'A"'
  3231.                       .  ' style="position:absolute;'
  3232.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3233.                       .  'top:' . $pos . 'px;';
  3234.                 if (isset($cellAttr[$i])) {
  3235.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3236.                 }
  3237.                 $html .= '"></div>' . PHP_EOL;
  3238.  
  3239.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3240.             }
  3241.         } else {
  3242.             // inactive cells first
  3243.             $pos = $cellAttr['spacing'];
  3244.             for ($i = 0; $i < $this->cellCount; $i++) {
  3245.                 $html .= $tabs . $tab
  3246.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3247.                       .  ' class="' . $cellCls . 'I"'
  3248.                       .  ' style="position:absolute;'
  3249.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3250.                       .  'top:' . $pos . 'px;'
  3251.                       .  '"></div>'
  3252.                       .  PHP_EOL;
  3253.  
  3254.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3255.             }
  3256.             // then active cells
  3257.             $pos = $cellAttr['spacing'];
  3258.             for ($i = 0; $i < $this->cellCount; $i++) {
  3259.                 $html .= $tabs . $tab
  3260.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3261.                       .  ' class="' . $cellCls . 'A"'
  3262.                       .  ' style="position:absolute;'
  3263.                       .  'left:' . $cellAttr['spacing'] . 'px;'
  3264.                       .  'top:' . $pos . 'px;';
  3265.                 if (isset($cellAttr[$i])) {
  3266.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3267.                 }
  3268.                 $html .= '"></div>' . PHP_EOL;
  3269.  
  3270.                 $pos += ($cellAttr['height'] + $cellAttr['spacing']);
  3271.             }
  3272.         }
  3273.         return $html;
  3274.     }
  3275.  
  3276.     /**
  3277.      * Returns a polygonal progress structure as HTML.
  3278.      *
  3279.      * @return     string
  3280.      * @since      2.0.0
  3281.      * @access     private
  3282.      */
  3283.     function _getProgressPolygonal_toHtml()
  3284.     {
  3285.         $tabs = $this->_getTabs();
  3286.         $tab = $this->_getTab();
  3287.         $way_natural = ($this->fillWay == 'natural');
  3288.         $cellAttr = $this->getCellAttributes();
  3289.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3290.         $coord = $this->getCellCoordinates();
  3291.         $html = '';
  3292.  
  3293.         if ($way_natural) {
  3294.             // inactive cells first
  3295.             for ($i = 0; $i < $this->cellCount; $i++) {
  3296.                 $top  = $coord[$i][0] * $cellAttr['width'];
  3297.                 $left = $coord[$i][1] * $cellAttr['height'];
  3298.                 $html .= $tabs . $tab
  3299.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3300.                       .  ' class="' . $cellCls . 'I"'
  3301.                       .  ' style="position:absolute;'
  3302.                       .  'left:' . $left . 'px;'
  3303.                       .  'top:' . $top . 'px;'
  3304.                       .  '"></div>'
  3305.                       .  PHP_EOL;
  3306.             }
  3307.             // then active cells
  3308.             for ($i = 0; $i < $this->cellCount; $i++) {
  3309.                 $top  = $coord[$i][0] * $cellAttr['width'];
  3310.                 $left = $coord[$i][1] * $cellAttr['height'];
  3311.                 $html .= $tabs . $tab
  3312.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3313.                       .  ' class="' . $cellCls . 'A"'
  3314.                       .  ' style="position:absolute;'
  3315.                       .  'left:' . $left . 'px;'
  3316.                       .  'top:' . $top . 'px;';
  3317.                 if (isset($cellAttr[$i])) {
  3318.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3319.                 }
  3320.                 $html .= '"></div>' . PHP_EOL;
  3321.             }
  3322.         } else {
  3323.             $c = count($coord) - 1;
  3324.             // inactive cells first
  3325.             for ($i = 0; $i < $this->cellCount; $i++) {
  3326.                 $top  = $coord[$c-$i][0] * $cellAttr['width'];
  3327.                 $left = $coord[$c-$i][1] * $cellAttr['height'];
  3328.                 $html .= $tabs . $tab
  3329.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3330.                       .  ' class="' . $cellCls . 'I"'
  3331.                       .  ' style="position:absolute;'
  3332.                       .  'left:' . $left . 'px;'
  3333.                       .  'top:' . $top . 'px;'
  3334.                       .  '"></div>'
  3335.                       .  PHP_EOL;
  3336.             }
  3337.             // then active cells
  3338.             for ($i = 0; $i < $this->cellCount; $i++) {
  3339.                 $top  = $coord[$c-$i][0] * $cellAttr['width'];
  3340.                 $left = $coord[$c-$i][1] * $cellAttr['height'];
  3341.                 $html .= $tabs . $tab
  3342.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3343.                       .  ' class="' . $cellCls . 'A"'
  3344.                       .  ' style="position:absolute;'
  3345.                       .  'left:' . $left . 'px;'
  3346.                       .  'top:' . $top . 'px;';
  3347.                 if (isset($cellAttr[$i])) {
  3348.                     $html .= 'color:' . $cellAttr[$i]['color'] . ';';
  3349.                 }
  3350.                 $html .= '"></div>' . PHP_EOL;
  3351.             }
  3352.         }
  3353.  
  3354.         return $html;
  3355.     }
  3356.  
  3357.     /**
  3358.      * Returns a circle progress structure as HTML.
  3359.      *
  3360.      * @return     string
  3361.      * @since      2.0.0
  3362.      * @access     private
  3363.      */
  3364.     function _getProgressCircle_toHtml()
  3365.     {
  3366.         $tabs = $this->_getTabs();
  3367.         $tab = $this->_getTab();
  3368.         $way_natural = ($this->fillWay == 'natural');
  3369.         $cellAttr = $this->getCellAttributes();
  3370.         $cellCls = sprintf($cellAttr['class'], $this->ident);
  3371.         $html = '';
  3372.  
  3373.         if ($way_natural) {
  3374.             // inactive cells first
  3375.             for ($i = 0; $i < $this->cellCount; $i++) {
  3376.                 $html .= $tabs . $tab
  3377.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3378.                       .  ' class="' . $cellCls . 'I"'
  3379.                       .  ' style="position:absolute;left:0;top:0;'
  3380.                       .  '"></div>'
  3381.                       .  PHP_EOL;
  3382.             }
  3383.             // then active cells
  3384.             for ($i = 0; $i < $this->cellCount; $i++) {
  3385.                 $html .= $tabs . $tab
  3386.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3387.                       .  ' class="' . $cellCls . 'A"'
  3388.                       .  ' style="position:absolute;left:0;top:0;'
  3389.                       .  '"><img src="' . $cellAttr[$i+1]['background-image'] . '" border="0" />'
  3390.                       .  '</div>'
  3391.                       .  PHP_EOL;
  3392.             }
  3393.         } else {
  3394.             // inactive cells first
  3395.             for ($i = 0; $i < $this->cellCount; $i++) {
  3396.                 $html .= $tabs . $tab
  3397.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'I' . $this->ident . '"'
  3398.                       .  ' class="' . $cellCls . 'I"'
  3399.                       .  ' style="position:absolute;left:0;top:0;'
  3400.                       .  '"></div>'
  3401.                       .  PHP_EOL;
  3402.             }
  3403.             // then active cells
  3404.             for ($i = 0; $i < $this->cellCount; $i++) {
  3405.                 $html .= $tabs . $tab
  3406.                       .  '<div id="' . sprintf($cellAttr['id'],$i) . 'A' . $this->ident . '"'
  3407.                       .  ' class="' . $cellCls . 'A"'
  3408.                       .  ' style="position:absolute;left:0;top:0;'
  3409.                       .  '"><img src="' . $cellAttr[$i+1]['background-image'] . '" border="0" />'
  3410.                       .  '</div>'
  3411.                       .  PHP_EOL;
  3412.             }
  3413.         }
  3414.         return $html;
  3415.     }
  3416.  
  3417.     /**
  3418.      * Computes all coordinates of a standard polygon (square or rectangle).
  3419.      *
  3420.      * @param      integer   $w             Polygon width
  3421.      * @param      integer   $h             Polygon height
  3422.      *
  3423.      * @return     array
  3424.      * @since      2.0.0
  3425.      * @access     private
  3426.      * @see        setCellCoordinates()
  3427.      */
  3428.     function _computeCoordinates($w, $h)
  3429.     {
  3430.         $coord = array();
  3431.  
  3432.         for ($y=0; $y<$h; $y++) {
  3433.             if ($y == 0) {
  3434.                 // creates top side line
  3435.                 for ($x=0; $x<$w; $x++) {
  3436.                     $coord[] = array($y, $x);
  3437.                 }
  3438.             } elseif ($y == ($h-1)) {
  3439.                 // creates bottom side line
  3440.                 for ($x=($w-1); $x>0; $x--) {
  3441.                     $coord[] = array($y, $x);
  3442.                 }
  3443.                 // creates left side line
  3444.                 for ($i=($h-1); $i>0; $i--) {
  3445.                     $coord[] = array($i, 0);
  3446.                 }
  3447.             } else {
  3448.                 // creates right side line
  3449.                 $coord[] = array($y, $w - 1);
  3450.             }
  3451.         }
  3452.         return $coord;
  3453.     }
  3454.  
  3455.     /**
  3456.      * Updates the new size of progress bar, depending of cell size, cell count
  3457.      * and border width.
  3458.      *
  3459.      * @since      2.0.0
  3460.      * @access     private
  3461.      * @see        setOrientation(), setCellCount(), setCellAttributes(),
  3462.      *             setBorderAttributes()
  3463.      */
  3464.     function _updateProgressSize()
  3465.     {
  3466.         if ($this->cellCount == 0) {
  3467.             return;
  3468.         }
  3469.  
  3470.         $cell_width   = $this->cell['width'];
  3471.         $cell_height  = $this->cell['height'];
  3472.         $cell_spacing = $this->cell['spacing'];
  3473.  
  3474.         $border_width = $this->border['width'];
  3475.  
  3476.         $cell_count = $this->cellCount;
  3477.  
  3478.         if ($this->orientation == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3479.             $w = ($cell_count * ($cell_width + $cell_spacing)) + $cell_spacing;
  3480.             $h = $cell_height + (2 * $cell_spacing);
  3481.         }
  3482.         if ($this->orientation == HTML_PROGRESS2_BAR_VERTICAL) {
  3483.             $w  = $cell_width + (2 * $cell_spacing);
  3484.             $h  = ($cell_count * ($cell_height + $cell_spacing)) + $cell_spacing;
  3485.         }
  3486.         if ($this->orientation == HTML_PROGRESS2_POLYGONAL) {
  3487.             $w  = $cell_width * $this->_xgrid;
  3488.             $h  = $cell_height * $this->_ygrid;
  3489.         }
  3490.         if ($this->orientation == HTML_PROGRESS2_CIRCLE) {
  3491.             $w  = $cell_width;
  3492.             $h  = $cell_height;
  3493.         }
  3494.  
  3495.         $attr = array ('width' => $w, 'height' => $h);
  3496.  
  3497.         $this->_updateAttrArray($this->_progress, $attr);
  3498.     }
  3499.  
  3500.     /**
  3501.      * Calculate the new position in pixel of the progress bar value.
  3502.      *
  3503.      * @return     void
  3504.      * @since      2.0.0
  3505.      * @access     private
  3506.      */
  3507.     function _computePosition()
  3508.     {
  3509.         $orient = $this->orientation;
  3510.         $progressAttr = $this->getProgressAttributes();
  3511.         $min = $this->minimum;
  3512.         $max = $this->maximum;
  3513.         $step = $this->value;
  3514.         $padding = 0;
  3515.  
  3516.         if ($orient == HTML_PROGRESS2_BAR_HORIZONTAL) {
  3517.             if ($this->fillWay == 'natural') {
  3518.                 $direction = 'right';
  3519.             } else {
  3520.                 $direction = 'left';
  3521.             }
  3522.         } else {
  3523.             if ($this->fillWay == 'natural') {
  3524.                 $direction = 'up';
  3525.             } else {
  3526.                 $direction = 'down';
  3527.             }
  3528.         }
  3529.  
  3530.         switch ($direction) {
  3531.             case 'right':
  3532.             case 'left':
  3533.                 $bar = $progressAttr['width'];
  3534.                 break;
  3535.             case 'down':
  3536.             case 'up':
  3537.                 $bar = $progressAttr['height'];
  3538.                 break;
  3539.         }
  3540.         $pixel = round(($step - $min) * ($bar - ($padding * 2)) / ($max - $min));
  3541.         if ($step <= $min) {
  3542.             $pixel = 0;
  3543.         }
  3544.         if ($step >= $max) {
  3545.             $pixel = $bar - ($padding * 2);
  3546.         }
  3547.  
  3548.         switch ($direction) {
  3549.             case 'right':
  3550.                 $position['left'] = $padding;
  3551.                 $position['top'] = $padding;
  3552.                 $position['width'] = $pixel;
  3553.                 $position['height'] = $progressAttr['height'] - ($padding * 2);
  3554.                 break;
  3555.             case 'left':
  3556.                 $position['left'] = $progressAttr['width'] - $padding - $pixel;
  3557.                 $position['top'] = $padding;
  3558.                 $position['width'] = $pixel;
  3559.                 $position['height'] = $progressAttr['height'] - ($padding * 2);
  3560.                 break;
  3561.             case 'down':
  3562.                 $position['left'] = $padding;
  3563.                 $position['top'] = $padding;
  3564.                 $position['width'] = $progressAttr['width'] - ($padding * 2);
  3565.                 $position['height'] = $pixel;
  3566.                 break;
  3567.             case 'up':
  3568.                 $position['left'] = $padding;
  3569.                 $position['top'] = $progressAttr['height'] - $padding - $pixel;
  3570.                 $position['width'] = $progressAttr['width'] - ($padding * 2);
  3571.                 $position['height'] = $pixel;
  3572.                 break;
  3573.         }
  3574.         return $position;
  3575.     }
  3576.  
  3577.     /**
  3578.      * Sends a DOM command (emulate firstChild.nodeValue) through a javascript function
  3579.      * to change label value of a progress bar's element.
  3580.      *
  3581.      * @param      string    $element       element name (label id.)
  3582.      * @param      string    $text          element value (label content)
  3583.      *
  3584.      * @return     void
  3585.      * @since      2.0.0
  3586.      * @access     private
  3587.      */
  3588.     function _changeLabelText($element, $text)
  3589.     {
  3590.         $cmd = '<script type="text/javascript">'
  3591.              . 'setLabelText'
  3592.              . '("' . $this->ident . '","' . $element . '","' . $text . '");'
  3593.              . '</script>';
  3594.  
  3595.         echo $cmd;
  3596.     }
  3597.  
  3598.     /**
  3599.      * Sends a DOM command through a javascript function
  3600.      * to change the next frame animation of a cross bar's element.
  3601.      *
  3602.      * @param      string    $element       element name (cross id.)
  3603.      *
  3604.      * @return     string
  3605.      * @since      2.0.0
  3606.      * @access     private
  3607.      */
  3608.     function _changeCrossItem($element)
  3609.     {
  3610.         $cmd = '<script type="text/javascript">'
  3611.              . 'setRotaryCross'
  3612.              . '("' . $this->ident . '","' . $element . '");'
  3613.              . '</script>';
  3614.  
  3615.         echo $cmd;
  3616.     }
  3617.  
  3618.     /**
  3619.      * Sends a DOM command (emulate cssText attribute) through a javascript function
  3620.      * to change styles of a progress bar's element.
  3621.      *
  3622.      * @param      string    $prefix        prefix identifier of the element
  3623.      * @param      string    $element       element name (label id.)
  3624.      * @param      string    $styles        styles of a DOM element
  3625.      *
  3626.      * @return     string
  3627.      * @since      2.0.0
  3628.      * @access     private
  3629.      */
  3630.     function _changeElementStyle($prefix, $element, $styles)
  3631.     {
  3632.         $cmd = '<script type="text/javascript">'
  3633.              . 'setElementStyle'
  3634.              . '("' . $prefix . '","' . $element . '","' . $this->ident . '","' . $styles . '");'
  3635.              . '</script>';
  3636.  
  3637.         return $cmd;
  3638.     }
  3639.  
  3640.     /**
  3641.      * Post a new notification to all observers registered.
  3642.      * This notification occured only if a dispatcher exists. That means if
  3643.      * at least one observer was registered.
  3644.      *
  3645.      * @param      string    $event         Name of the notification handler
  3646.      * @param      array     $info          (optional) Additional information about the notification
  3647.      *
  3648.      * @return     void
  3649.      * @since      2.0.0RC2
  3650.      * @access     private
  3651.      */
  3652.     function _postNotification($event, $info = array())
  3653.     {
  3654.         if (isset($this->dispatcher)) {
  3655.             $info['sender'] = get_class($this);
  3656.             $info['time']   = microtime();
  3657.             $this->dispatcher->post($this, $event, $info);
  3658.         }
  3659.     }
  3660.  
  3661.     /**
  3662.      * Initialize Error Handler
  3663.      *
  3664.      * Parameter '$prefs' contains a hash of options to define the error handler.
  3665.      * You may find :
  3666.      *  'message_callback'  A callback to generate message body.
  3667.      *                      Default is:  HTML_Progress2_Error::_msgCallback()
  3668.      *  'context_callback'  A callback to generate context of error.
  3669.      *                      Default is:  HTML_Progress2_Error::getBacktrace()
  3670.      *  'push_callback'     A callback to determine whether to allow an error
  3671.      *                      to be pushed or logged.
  3672.      *                      Default is:  HTML_Progress2_Error::_handleError()
  3673.      *  'error_handler'     A callback to manage all error raised.
  3674.      *                      Default is:  HTML_Progress2::_errorHandler()
  3675.      *  'handler'           Hash of params to configure all handlers (display, file, mail ...)
  3676.      *                      There are only a display handler by default with options below:
  3677.      *
  3678.      * @param      array     $prefs         hash of params to configure error handler
  3679.      *
  3680.      * @return     void
  3681.      * @since      2.0.0
  3682.      * @access     private
  3683.      */
  3684.     function _initErrorHandler($prefs = array())
  3685.     {
  3686.         // error message mapping callback
  3687.         if (isset($prefs['message_callback']) && is_callable($prefs['message_callback'])) {
  3688.             $this->_callback_message = $prefs['message_callback'];
  3689.         } else {
  3690.             $this->_callback_message = array('HTML_Progress2_Error', '_msgCallback');
  3691.         }
  3692.  
  3693.         // error context mapping callback
  3694.         if (isset($prefs['context_callback']) && is_callable($prefs['context_callback'])) {
  3695.             $this->_callback_context = $prefs['context_callback'];
  3696.         } else {
  3697.             $this->_callback_context = array('HTML_Progress2_Error', 'getBacktrace');
  3698.         }
  3699.  
  3700.         // determine whether to allow an error to be pushed or logged
  3701.         if (isset($prefs['push_callback']) && is_callable($prefs['push_callback'])) {
  3702.             $this->_callback_push = $prefs['push_callback'];
  3703.         } else {
  3704.             $this->_callback_push = array('HTML_Progress2_Error', '_handleError');
  3705.         }
  3706.  
  3707.         // default error handler will use PEAR_Error
  3708.         if (isset($prefs['error_handler']) && is_callable($prefs['error_handler'])) {
  3709.             $this->_callback_errorhandler = $prefs['error_handler'];
  3710.         } else {
  3711.             $this->_callback_errorhandler = array(&$this, '_errorHandler');
  3712.         }
  3713.  
  3714.         // any handler-specific settings
  3715.         if (isset($prefs['handler'])) {
  3716.             $this->_errorhandler_options = $prefs['handler'];
  3717.         }
  3718.     }
  3719.  
  3720.     /**
  3721.      * Standard error handler that will use PEAR_Error object
  3722.      *
  3723.      * To improve performances, the PEAR.php file is included dynamically.
  3724.      * The file is so included only when an error is triggered. So, in most
  3725.      * cases, the file isn't included and perfs are much better.
  3726.      *
  3727.      * @param      integer   $code          Error code
  3728.      * @param      string    $level         Error level
  3729.      * @param      array     $params        Associative array of error parameters
  3730.      *
  3731.      * @return     PEAR_Error
  3732.      * @since      2.0.0
  3733.      * @access     private
  3734.      */
  3735.     function _errorHandler($code, $level, $params)
  3736.     {
  3737.         include_once 'HTML/Progress2/Error.php';
  3738.  
  3739.         $mode = call_user_func($this->_callback_push, $code, $level);
  3740.  
  3741.         $message = call_user_func($this->_callback_message, $code, $params);
  3742.         $userinfo['level'] = $level;
  3743.  
  3744.         if (isset($this->_errorhandler_options['display'])) {
  3745.             $userinfo['display'] = $this->_errorhandler_options['display'];
  3746.         } else {
  3747.             $userinfo['display'] = array();
  3748.         }
  3749.         if (isset($this->_errorhandler_options['log'])) {
  3750.             $userinfo['log'] = $this->_errorhandler_options['log'];
  3751.         } else {
  3752.             $userinfo['log'] = array();
  3753.         }
  3754.  
  3755.         return PEAR::raiseError($message, $code, $mode, null, $userinfo, 'HTML_Progress2_Error');
  3756.     }
  3757.  
  3758.     /**
  3759.      * A basic wrapper around the default PEAR_Error object.
  3760.      *
  3761.      * This method throws any internal API error that could be raised
  3762.      * due to a wrong programming. It will use your error handler system defined
  3763.      * at class construction (by first argument).
  3764.      *
  3765.      * @return     mixed
  3766.      * @since      2.0.0
  3767.      * @access     public
  3768.      * @see        _errorHandler()
  3769.      */
  3770.     function raiseError()
  3771.     {
  3772.         $args = func_get_args();
  3773.         $err = call_user_func_array($this->_callback_errorhandler, $args);
  3774.         if (is_null($err)) {
  3775.             $err = array('code' => $args[0], 'level' => $args[1], 'params' => $args[2]);
  3776.         }
  3777.         array_push($this->_errorstack, $err);
  3778.         return $err;
  3779.     }
  3780.  
  3781.     /**
  3782.      * Determine whether there are errors into the HTML_Progress2 stack.
  3783.      *
  3784.      * This function gave you ability to be aware of API errors presence
  3785.      * in user scripts.
  3786.      *
  3787.      * @return     integer
  3788.      * @since      2.0.0
  3789.      * @access     public
  3790.      * @see        getError(), raiseError()
  3791.      */
  3792.     function hasErrors()
  3793.     {
  3794.         return count($this->_errorstack);
  3795.     }
  3796.  
  3797.     /**
  3798.      * Pop an error off of the HTML_Progress2 stack.
  3799.      *
  3800.      * Get all error data (code, message, level, context) from an object (PEAR_Error, ...)
  3801.      * or a simple php array.
  3802.      *
  3803.      * @return     false|array|PEAR_Error
  3804.      * @since      2.0.0
  3805.      * @access     public
  3806.      * @see        hasErrors(), raiseError()
  3807.      */
  3808.     function getError()
  3809.     {
  3810.         return @array_shift($this->_errorstack);
  3811.     }
  3812. }
  3813. ?>