home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / HTML / Progress2.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  154.0 KB  |  4,396 lines

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