| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |