1<?php 2/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ 3 4namespace Icinga\Chart\Graph; 5 6use DOMElement; 7use Icinga\Chart\Primitive\Animation; 8use Icinga\Chart\Primitive\Drawable; 9use Icinga\Chart\Primitive\Rect; 10use Icinga\Chart\Primitive\Styleable; 11use Icinga\Chart\Render\RenderContext; 12 13/** 14 * Bar graph implementation 15 */ 16class BarGraph extends Styleable implements Drawable 17{ 18 /** 19 * The dataset order 20 * 21 * @var int 22 */ 23 private $order = 0; 24 25 /** 26 * The width of the bars. 27 * 28 * @var int 29 */ 30 private $barWidth = 3; 31 32 /** 33 * The dataset to use for this bar graph 34 * 35 * @var array 36 */ 37 private $dataSet; 38 39 /** 40 * The tooltips 41 * 42 * @var 43 */ 44 private $tooltips; 45 46 /** 47 * All graphs 48 * 49 * @var 50 */ 51 private $graphs; 52 53 /** 54 * Create a new BarGraph with the given dataset 55 * 56 * @param array $dataSet An array of data points 57 * @param int $order The graph number displayed by this BarGraph 58 * @param array $tooltips The tooltips to display for each value 59 */ 60 public function __construct( 61 array $dataSet, 62 array &$graphs, 63 $order, 64 array $tooltips = null 65 ) { 66 $this->order = $order; 67 $this->dataSet = $dataSet; 68 69 $this->tooltips = $tooltips; 70 foreach ($this->tooltips as $value) { 71 $ts[] = $value; 72 } 73 $this->tooltips = $ts; 74 75 $this->graphs = $graphs; 76 } 77 78 /** 79 * Apply configuration styles from the $cfg 80 * 81 * @param array $cfg The configuration as given in the drawBars call 82 */ 83 public function setStyleFromConfig(array $cfg) 84 { 85 foreach ($cfg as $elem => $value) { 86 if ($elem === 'color') { 87 $this->setFill($value); 88 } elseif ($elem === 'width') { 89 $this->setStrokeWidth($value); 90 } 91 } 92 } 93 94 /** 95 * Draw a single rectangle 96 * 97 * @param array $point The 98 * @param string $fill The fill color to use 99 * @param $strokeWidth 100 * @param null $index 101 * 102 * @return Rect 103 */ 104 private function drawSingleBar($point, $fill, $strokeWidth, $index = null) 105 { 106 $rect = new Rect($point[0] - ($this->barWidth / 2), $point[1], $this->barWidth, 100 - $point[1]); 107 $rect->setFill($fill); 108 $rect->setStrokeWidth($strokeWidth); 109 $rect->setStrokeColor('black'); 110 if (isset($index)) { 111 $rect->setAttribute('data-icinga-graph-index', $index); 112 } 113 $rect->setAttribute('data-icinga-graph-type', 'bar'); 114 $rect->setAdditionalStyle('clip-path: url(#clip);'); 115 return $rect; 116 } 117 118 /** 119 * Render this BarChart 120 * 121 * @param RenderContext $ctx The rendering context to use for drawing 122 * 123 * @return DOMElement $dom Element 124 */ 125 public function toSvg(RenderContext $ctx) 126 { 127 $doc = $ctx->getDocument(); 128 $group = $doc->createElement('g'); 129 $idx = 0; 130 131 if (count($this->dataSet) > 15) { 132 $this->barWidth = 2; 133 } 134 if (count($this->dataSet) > 25) { 135 $this->barWidth = 1; 136 } 137 138 foreach ($this->dataSet as $x => $point) { 139 // add white background bar, to prevent other bars from altering transparency effects 140 $bar = $this->drawSingleBar($point, 'white', $this->strokeWidth, $idx++)->toSvg($ctx); 141 $group->appendChild($bar); 142 143 // draw actual bar 144 $bar = $this->drawSingleBar($point, $this->fill, $this->strokeWidth)->toSvg($ctx); 145 if (isset($this->tooltips[$x])) { 146 $data = array( 147 'label' => isset($this->graphs[$this->order]['label']) ? 148 strtolower($this->graphs[$this->order]['label']) : '', 149 'color' => isset($this->graphs[$this->order]['color']) ? 150 strtolower($this->graphs[$this->order]['color']) : '#fff' 151 ); 152 $format = isset($this->graphs[$this->order]['tooltip']) 153 ? $this->graphs[$this->order]['tooltip'] : null; 154 $title = $ctx->getDocument()->createElement('title'); 155 $title->textContent = $this->tooltips[$x]->renderNoHtml($this->order, $data, $format); 156 $bar->appendChild($title); 157 } 158 $group->appendChild($bar); 159 } 160 return $group; 161 } 162} 163