[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/library/ezc/Graph/src/axis/ -> labeled.php (source)

   1  <?php
   2  /**
   3   * File containing the ezcGraphChartElementLabeledAxis class
   4   *
   5   * @package Graph
   6   * @version 1.5
   7   * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
   8   * @license http://ez.no/licenses/new_bsd New BSD License
   9   */
  10  /**
  11   * Class to represent a labeled axis.
  12   *
  13   * Axis elements represent the axis in a bar, line or radar chart. They are
  14   * chart elements (ezcGraphChartElement) extending from
  15   * ezcGraphChartElementAxis, where additional formatting options can be found.
  16   * You should generally use the axis, which matches your input data best, so
  17   * that the automatic chart layouting works best. Aavailable axis types are:
  18   *
  19   * - ezcGraphChartElementDateAxis
  20   * - ezcGraphChartElementLabeledAxis
  21   * - ezcGraphChartElementLogarithmicalAxis
  22   * - ezcGraphChartElementNumericAxis
  23   *
  24   * The labeled axis will accept any values and converts them to strings. The
  25   * labeled axis does not know about any special meanings of values and
  26   * maintains the order of the given labels with equidistant spaces between all
  27   * values. If your data has a special meaning, like a set of numbers or dates,
  28   * use one of the other more appropriate axis.
  29   *
  30   * Because it is not always possible to fit all labels in a chart you may
  31   * define the count of labels drawn using the $labelCount option. For all other
  32   * labels only a small step will be rendered.
  33   *
  34   * The labeled axis may be used like:
  35   *
  36   * <code>
  37   *  $graph = new ezcGraphLineChart();
  38   *  $graph->options->fillLines = 210;
  39   *  $graph->options->font->maxFontSize = 10;
  40   *  $graph->title = 'Error level colors';
  41   *  $graph->legend = false;
  42   *  
  43   *  $graph->yAxis = new ezcGraphChartElementLabeledAxis();
  44   *  $graph->yAxis->axisLabelRenderer->showZeroValue = true;
  45   *  
  46   *  $graph->yAxis->label = 'Color';
  47   *  $graph->xAxis->label = 'Error level';
  48   *  
  49   *  // Add data
  50   *  $graph->data['colors'] = new ezcGraphArrayDataSet(
  51   *      array(
  52   *          'info' => 'blue',
  53   *          'notice' => 'green',
  54   *          'warning' => 'orange',
  55   *          'error' => 'red',
  56   *          'fatal' => 'red',
  57   *      )
  58   *  );
  59   *  
  60   *  $graph->render( 400, 150, 'tutorial_axis_labeled.svg' );
  61   * </code>
  62   *
  63   * @property float $labelCount
  64   *           Define count of displayed labels on the axis
  65   * 
  66   * @version 1.5
  67   * @package Graph
  68   * @mainclass
  69   */
  70  class ezcGraphChartElementLabeledAxis extends ezcGraphChartElementAxis
  71  {
  72      /**
  73       * Array with labeles for data 
  74       * 
  75       * @var array
  76       */
  77      protected $labels = array();
  78  
  79      /**
  80       * Labels indexed by their name as key for faster lookups
  81       * 
  82       * @var array
  83       */
  84      protected $labelsIndexed = array();
  85  
  86      /**
  87       * Reduced amount of labels which will be displayed in the chart
  88       * 
  89       * @var array
  90       */
  91      protected $displayedLabels = array();
  92  
  93      /**
  94       * Maximum count of labels which can be displayed on one axis
  95       * @todo Perhaps base this on the chart size
  96       */
  97      const MAX_LABEL_COUNT = 10;
  98  
  99      /**
 100       * Precalculated steps on the axis
 101       * 
 102       * @var array(ezcGraphAxisStep)
 103       */
 104      protected $steps;
 105  
 106      /**
 107       * Constructor
 108       * 
 109       * @param array $options Default option array
 110       * @return void
 111       * @ignore
 112       */
 113      public function __construct( array $options = array() )
 114      {
 115          $this->properties['labelCount'] = null;
 116  
 117          $this->axisLabelRenderer = new ezcGraphAxisCenteredLabelRenderer();
 118  
 119          parent::__construct( $options );
 120      }
 121  
 122      /**
 123       * __set 
 124       * 
 125       * @param mixed $propertyName 
 126       * @param mixed $propertyValue 
 127       * @throws ezcBaseValueException
 128       *          If a submitted parameter was out of range or type.
 129       * @throws ezcBasePropertyNotFoundException
 130       *          If a the value for the property options is not an instance of
 131       * @return void
 132       * @ignore
 133       */
 134      public function __set( $propertyName, $propertyValue )
 135      {
 136          switch ( $propertyName )
 137          {
 138              case 'labelCount':
 139                  if ( !is_numeric( $propertyValue ) ||
 140                       ( $propertyValue <= 1 ) )
 141                  {
 142                      throw new ezcBaseValueException( $propertyName, $propertyValue, 'int > 1' );
 143                  }
 144  
 145                  $this->properties['labelCount'] = (int) $propertyValue;
 146                  break;
 147              default:
 148                  parent::__set( $propertyName, $propertyValue );
 149                  break;
 150          }
 151      }
 152  
 153      /**
 154       * Increase the keys of all elements in the array up from the start key, to
 155       * insert an additional element at the correct position.
 156       * 
 157       * @param array $array Array
 158       * @param int $startKey Key to increase keys from
 159       * @return array Updated array
 160       */
 161      protected function increaseKeys( array $array, $startKey )
 162      {
 163          foreach ( $array as $key => $value )
 164          {
 165              if ( $key === $startKey )
 166              {
 167                  // Recursive check, if next key should be increased, too
 168                  if ( isset ( $array[$key + 1] ) )
 169                  {
 170                      $array = $this->increaseKeys( $array, $key + 1 );
 171                  }
 172  
 173                  // Increase key
 174                  $array[$key + 1] = $array[$key];
 175                  unset( $array[$key] );
 176              }
 177          }
 178  
 179          return $array;
 180      }
 181  
 182      /**
 183       * Provide initial set of labels
 184       *
 185       * This method may be used to provide an ordered set of labels, containing
 186       * labels, which are not available in the datasets or to provide a label
 187       * order different to the one in the given dataset.
 188       * 
 189       * @param array $labels 
 190       * @return void
 191       */
 192      public function provideLabels( array $labels )
 193      {
 194          $this->addData( $labels );
 195      }
 196  
 197      /**
 198       * Add data for this axis
 199       * 
 200       * @param array $values Value which will be displayed on this axis
 201       * @return void
 202       */
 203      public function addData( array $values )
 204      {
 205          $position = 0;
 206          foreach ( $values as $label )
 207          {
 208              $label = (string) $label;
 209  
 210              if ( !in_array( $label, $this->labels, true ) )
 211              {
 212                  if ( isset( $this->labels[$position] ) )
 213                  {
 214                      $this->labels = $this->increaseKeys( $this->labels, $position );
 215                      $this->labels[$position++] = $label;
 216                  }
 217                  else
 218                  {
 219                      $this->labels[$position++] = $label;
 220                  }
 221              }
 222              else 
 223              {
 224                  $position = array_search( $label, $this->labels, true ) + 1;
 225              }
 226          }
 227          ksort( $this->labels );
 228          $this->labelsIndexed = array_flip( $this->labels );
 229  
 230          $this->properties['initialized'] = true;
 231      }
 232  
 233      /**
 234       * Calculate axis bounding values on base of the assigned values 
 235       * 
 236       * @abstract
 237       * @access public
 238       * @return void
 239       */
 240      public function calculateAxisBoundings()
 241      {
 242          $this->steps = array();
 243  
 244          // Apply label format callback function
 245          if ( $this->properties['labelCallback'] !==  null )
 246          {
 247              foreach ( $this->labels as $nr => $label )
 248              {
 249                  $this->labels[$nr] = call_user_func_array(
 250                      $this->properties['labelCallback'],
 251                      array(
 252                          $label,
 253                          $nr
 254                      )
 255                  );
 256              }
 257          }
 258  
 259          $labelCount = count( $this->labels ) - 1;
 260  
 261          if ( $labelCount === 0 )
 262          {
 263              // Create single only step
 264              $this->steps = array(
 265                  new ezcGraphAxisStep(
 266                      0,
 267                      1,
 268                      reset( $this->labels ),
 269                      array(),
 270                      true,
 271                      true
 272                  ),
 273              );
 274  
 275              return true;
 276          }
 277  
 278          if ( $this->properties['labelCount'] === null )
 279          {
 280              if ( $labelCount <= self::MAX_LABEL_COUNT )
 281              {
 282                  $stepSize = 1 / $labelCount;
 283  
 284                  foreach ( $this->labels as $nr => $label )
 285                  {
 286                      $this->steps[] = new ezcGraphAxisStep(
 287                          $stepSize * $nr,
 288                          $stepSize,
 289                          $label,
 290                          array(),
 291                          $nr === 0,
 292                          $nr === $labelCount
 293                      );
 294                  }
 295  
 296                  // @TODO: This line is deprecated and only build for 
 297                  // deprecated getLabel()
 298                  $this->displayedLabels = $this->labels;
 299  
 300                  return true;
 301              }
 302  
 303              for ( $div = self::MAX_LABEL_COUNT; $div > 1; --$div )
 304              {
 305                  if ( ( $labelCount % $div ) === 0 )
 306                  {
 307                      // @TODO: This part is deprecated and only build for 
 308                      // deprecated getLabel()
 309                      $step = $labelCount / $div;
 310  
 311                      foreach ( $this->labels as $nr => $label )
 312                      {
 313                          if ( ( $nr % $step ) === 0 )
 314                          {
 315                              $this->displayedLabels[] = $label;
 316                          }
 317                      }
 318                      // End of deprecated part
 319  
 320                      break;
 321                  }
 322              }
 323          }
 324          else
 325          {
 326              $div = false;
 327          }
 328  
 329          // Build up step array
 330          if ( $div > 2 )
 331          {
 332              $step = $labelCount / $div;
 333              $stepSize = 1 / $div;
 334              $minorStepSize = $stepSize / $step;
 335  
 336              foreach ( $this->labels as $nr => $label )
 337              {
 338                  if ( ( $nr % $step ) === 0 )
 339                  {
 340                      $mainstep = new ezcGraphAxisStep(
 341                          $stepSize * ( $nr / $step ),
 342                          $stepSize,
 343                          $label,
 344                          array(),
 345                          $nr === 0,
 346                          $nr === $labelCount
 347                      );
 348  
 349                      $this->steps[] = $mainstep;
 350                  }
 351                  else
 352                  {
 353                      $mainstep->childs[] = new ezcGraphAxisStep(
 354                          $mainstep->position + $minorStepSize * ( $nr % $step ),
 355                          $minorStepSize
 356                      );
 357                  }
 358              }
 359          }
 360          else
 361          {
 362              if ( $this->properties['labelCount'] === null )
 363              {
 364                  $floatStep = $labelCount / ( self::MAX_LABEL_COUNT - 1 );
 365              }
 366              else
 367              {
 368                  $floatStep = $labelCount / min( $labelCount, $this->properties['labelCount'] - 1 );
 369              }
 370  
 371              $position = 0;
 372              $minorStepSize = 1 / $labelCount;
 373              
 374              foreach ( $this->labels as $nr => $label )
 375              {
 376                  if ( $nr >= $position )
 377                  {
 378                      $position += $floatStep;
 379  
 380                      // Add as major step
 381                      $mainstep = new ezcGraphAxisStep(
 382                          $minorStepSize * $nr,
 383                          ceil( $position - $nr ) * $minorStepSize,
 384                          $label,
 385                          array(),
 386                          $nr === 0,
 387                          $nr === $labelCount
 388                      );
 389  
 390                      // @TODO: This line is deprecated and only build for 
 391                      // deprecated getLabel()
 392                      $this->displayedLabels[] = $label;
 393  
 394                      $this->steps[] = $mainstep;
 395                  }
 396                  else
 397                  {
 398                      $mainstep->childs[] = new ezcGraphAxisStep(
 399                          $minorStepSize * $nr,
 400                          $minorStepSize
 401                      );
 402                  }
 403              }
 404          }
 405      }
 406  
 407      /**
 408       * Return array of steps on this axis
 409       * 
 410       * @return array( ezcGraphAxisStep )
 411       */
 412      public function getSteps()
 413      {
 414          return $this->steps;
 415      }
 416  
 417      /**
 418       * Get coordinate for a dedicated value on the chart
 419       * 
 420       * @param string $value Value to determine position for
 421       * @return float Position on chart
 422       */
 423      public function getCoordinate( $value )
 424      {
 425          if ( ( $value === false ) || 
 426               ( $value === null ) ||
 427               ( !isset( $this->labelsIndexed[$value] ) ) )
 428          {
 429              switch ( $this->position )
 430              {
 431                  case ezcGraph::LEFT:
 432                  case ezcGraph::TOP:
 433                      return 0.;
 434                  case ezcGraph::RIGHT:
 435                  case ezcGraph::BOTTOM:
 436                      return 1.;
 437              }
 438          }
 439          else
 440          {
 441              $key = $this->labelsIndexed[$value];
 442              switch ( $this->position )
 443              {
 444                  case ezcGraph::LEFT:
 445                  case ezcGraph::TOP:
 446                      if ( count( $this->labels ) > 1 )
 447                      {
 448                          return (float) $key / ( count ( $this->labels ) - 1 );
 449                      }
 450                      else
 451                      {
 452                          return 0;
 453                      }
 454                  case ezcGraph::BOTTOM:
 455                  case ezcGraph::RIGHT:
 456                      if ( count( $this->labels ) > 1 )
 457                      {
 458                          return (float) 1 - $key / ( count ( $this->labels ) - 1 );
 459                      }
 460                      else
 461                      {
 462                          return 1;
 463                      }
 464              }
 465          }
 466      }
 467  
 468      /**
 469       * Return count of minor steps
 470       * 
 471       * @return integer Count of minor steps
 472       */
 473      public function getMinorStepCount()
 474      {
 475          return 0;
 476      }
 477  
 478      /**
 479       * Return count of major steps
 480       * 
 481       * @return integer Count of major steps
 482       */
 483      public function getMajorStepCount()
 484      {
 485          return max( count( $this->displayedLabels ) - 1, 1 );
 486      }
 487  
 488      /**
 489       * Get label for a dedicated step on the axis
 490       * 
 491       * @param integer $step Number of step
 492       * @return string label
 493       */
 494      public function getLabel( $step )
 495      {
 496          if ( isset( $this->displayedLabels[$step] ) )
 497          {
 498              return $this->displayedLabels[$step];
 499          }
 500          else
 501          {
 502              return false;
 503          }
 504      }
 505  
 506      /**
 507       * Is zero step
 508       *
 509       * Returns true if the given step is the one on the initial axis position
 510       * 
 511       * @param int $step Number of step
 512       * @return bool Status If given step is initial axis position
 513       */
 514      public function isZeroStep( $step )
 515      {
 516          return !$step;
 517      }
 518  }
 519  
 520  ?>


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7