Inheritance: extends BarGraph
 protected function Draw()
 {
     $body = $this->Grid() . $this->Guidelines(SVGG_GUIDELINE_BELOW);
     $chunk_count = count($this->multi_graph);
     list($chunk_width, $bspace, $chunk_unit_width) = GroupedBarGraph::BarPosition($this->bar_width, $this->x_axes[$this->main_x_axis]->Unit(), $chunk_count, $this->bar_space, $this->group_space);
     $bar = array('width' => $chunk_width);
     $this->ColourSetup($this->multi_graph->ItemsCount(-1), $chunk_count);
     $this->block_width = $chunk_width;
     list($this->bx, $this->by) = $this->Project(-1, 0, $chunk_width);
     // make the top parallelogram, set it as a symbol for re-use
     $top = $this->BarTop();
     $bnum = 0;
     // get the translation for the whole bar
     // unit space is 1 deep * $chunk_count wide
     list($tx, $ty) = $this->Project(0, 0, $bspace);
     $all_group = array();
     if ($tx || $ty) {
         $all_group['transform'] = "translate({$tx},{$ty})";
     }
     if ($this->semantic_classes) {
         $all_group['class'] = 'series';
     }
     $bars = '';
     $group = array();
     foreach ($this->multi_graph as $itemlist) {
         $k = $itemlist[0]->key;
         $bar_pos = $this->GridPosition($k, $bnum);
         if (!is_null($bar_pos)) {
             for ($j = 0; $j < $chunk_count; ++$j) {
                 $bar['x'] = $bspace + $bar_pos + $j * $chunk_unit_width;
                 $item = $itemlist[$j];
                 if (!is_null($item->value)) {
                     $bar_sections = $this->Bar3D($item, $bar, $top, $bnum, $j, NULL, $this->DatasetYAxis($j));
                     $group['fill'] = $this->GetColour($item, $bnum, $j);
                     $show_label = $this->AddDataLabel($j, $bnum, $group, $item, $bar['x'] + $tx, $bar['y'] + $ty, $bar['width'], $bar['height']);
                     if ($this->show_tooltips) {
                         $this->SetTooltip($group, $item, $j, $item->key, $item->value);
                     }
                     $link = $this->GetLink($item, $k, $bar_sections);
                     $this->SetStroke($group, $item, $j, 'round');
                     if ($this->semantic_classes) {
                         $group['class'] = "series{$j}";
                     }
                     $bars .= $this->Element('g', $group, NULL, $link);
                     unset($group['id'], $group['class']);
                     if (!array_key_exists($j, $this->bar_styles)) {
                         $this->bar_styles[$j] = $group;
                     }
                 }
             }
         }
         ++$bnum;
     }
     if (count($all_group)) {
         $bars = $this->Element('g', $all_group, NULL, $bars);
     }
     $body .= $bars;
     $body .= $this->Guidelines(SVGG_GUIDELINE_ABOVE) . $this->Axes();
     return $body;
 }
 protected function Draw()
 {
     $body = $this->Grid() . $this->Guidelines(SVGG_GUIDELINE_BELOW);
     $chunk_count = count($this->multi_graph);
     list($chunk_width, $bspace, $chunk_unit_width) = GroupedBarGraph::BarPosition($this->bar_width, $this->x_axes[$this->main_x_axis]->Unit(), $chunk_count, $this->bar_space, $this->group_space);
     $bar_style = array();
     $bar = array('width' => $chunk_width);
     $this->ColourSetup($this->multi_graph->ItemsCount(-1), $chunk_count);
     $bnum = 0;
     $bars_shown = array_fill(0, $chunk_count, 0);
     $bars = '';
     foreach ($this->multi_graph as $itemlist) {
         $k = $itemlist[0]->key;
         $bar_pos = $this->GridPosition($k, $bnum);
         if (!is_null($bar_pos)) {
             for ($j = 0; $j < $chunk_count; ++$j) {
                 $bar['x'] = $bspace + $bar_pos + $j * $chunk_unit_width;
                 $item = $itemlist[$j];
                 $this->SetStroke($bar_style, $item, $j);
                 $bar_style['fill'] = $this->GetColour($item, $bnum, $j);
                 if (!is_null($item->value)) {
                     $this->Bar($item->value, $bar, NULL, $this->DatasetYAxis($j));
                     if ($bar['height'] > 0) {
                         ++$bars_shown[$j];
                         $show_label = $this->AddDataLabel($j, $bnum, $bar, $item, $bar['x'], $bar['y'], $bar['width'], $bar['height']);
                         if ($this->show_tooltips) {
                             $this->SetTooltip($bar, $item, $j, $item->key, $item->value, !$this->compat_events && $show_label);
                         }
                         if ($this->semantic_classes) {
                             $bar['class'] = "series{$j}";
                         }
                         $rect = $this->Element('rect', $bar, $bar_style);
                         $bars .= $this->GetLink($item, $k, $rect);
                         unset($bar['id']);
                         // clear for next generated value
                     }
                 }
                 $this->bar_styles[$j] = $bar_style;
             }
         }
         ++$bnum;
     }
     if (!$this->legend_show_empty) {
         foreach ($bars_shown as $j => $bar) {
             if (!$bar) {
                 $this->bar_styles[$j] = NULL;
             }
         }
     }
     if ($this->semantic_classes) {
         $bars = $this->Element('g', array('class' => 'series'), NULL, $bars);
     }
     $body .= $bars;
     $body .= $this->Guidelines(SVGG_GUIDELINE_ABOVE) . $this->Axes();
     return $body;
 }
 protected function Draw()
 {
     $body = $this->Grid() . $this->UnderShapes();
     $chunk_count = count($this->multi_graph);
     list($chunk_height, $bspace, $chunk_unit_height) = GroupedBarGraph::BarPosition($this->bar_width, $this->bar_width_min, $this->y_axes[$this->main_y_axis]->Unit(), $chunk_count, $this->bar_space, $this->group_space);
     $bar_style = array();
     $bar = array('height' => $chunk_height);
     $this->ColourSetup($this->multi_graph->ItemsCount(-1), $chunk_count);
     $bnum = 0;
     $bars = '';
     foreach ($this->multi_graph as $itemlist) {
         $item = $itemlist[0];
         $k = $item->key;
         $bar_pos = $this->GridPosition($item, $bnum);
         if (!is_null($bar_pos)) {
             for ($j = 0; $j < $chunk_count; ++$j) {
                 $bar['y'] = $bar_pos - $bspace - $chunk_height - $j * $chunk_unit_height;
                 $item = $itemlist[$j];
                 $this->SetStroke($bar_style, $item, $j);
                 $bar_style['fill'] = $this->GetColour($item, $bnum, $j);
                 $this->Bar($item->value, $bar);
                 if ($bar['width'] > 0) {
                     $show_label = $this->AddDataLabel($j, $bnum, $bar, $item, $bar['x'], $bar['y'], $bar['width'], $bar['height']);
                     if ($this->show_tooltips) {
                         $this->SetTooltip($bar, $item, $j, $item->key, $item->value, !$this->compat_events && $show_label);
                     }
                     if ($this->semantic_classes) {
                         $bar['class'] = "series{$j}";
                     }
                     $rect = $this->Element('rect', $bar, $bar_style);
                     $bars .= $this->GetLink($item, $k, $rect);
                     unset($bar['id']);
                     // clear ID for next generated value
                 }
                 $this->SetLegendEntry($j, $bnum, $item, $bar_style);
             }
         }
         ++$bnum;
     }
     if ($this->semantic_classes) {
         $bars = $this->Element('g', array('class' => 'series'), NULL, $bars);
     }
     $body .= $bars;
     $body .= $this->OverShapes();
     $body .= $this->Axes();
     return $body;
 }
 protected function Draw()
 {
     if ($this->log_axis_y) {
         throw new Exception('log_axis_y not supported by StackedGroupedBarGraph');
     }
     $body = $this->Grid() . $this->UnderShapes();
     $group_count = count($this->groups);
     list($group_width, $bspace, $group_unit_width) = GroupedBarGraph::BarPosition($this->bar_width, $this->bar_width_min, $this->x_axes[$this->main_x_axis]->Unit(), $group_count, $this->bar_space, $this->group_space);
     $bar_style = array();
     $bar = array('width' => $group_width);
     $bnum = 0;
     $bar_count = count($this->multi_graph);
     $bars_shown = array_fill(0, $bar_count, 0);
     // for legend yes/no
     $bars = '';
     $this->ColourSetup($this->multi_graph->ItemsCount(-1), $bar_count);
     foreach ($this->multi_graph as $itemlist) {
         $k = $itemlist[0]->key;
         $bar_pos = $this->GridPosition($k, $bnum);
         if (!is_null($bar_pos)) {
             for ($l = 0; $l < $group_count; ++$l) {
                 $bar['x'] = $bspace + $bar_pos + $l * $group_unit_width;
                 $start_bar = $this->groups[$l];
                 $end_bar = isset($this->groups[$l + 1]) ? $this->groups[$l + 1] : $bar_count;
                 $ypos = $yneg = 0;
                 // find greatest -/+ bar
                 $max_neg_bar = $max_pos_bar = -1;
                 for ($j = $start_bar; $j < $end_bar; ++$j) {
                     if ($itemlist[$j]->value > 0) {
                         $max_pos_bar = $j;
                     } else {
                         $max_neg_bar = $j;
                     }
                 }
                 for ($j = $start_bar; $j < $end_bar; ++$j) {
                     $item = $itemlist[$j];
                     $this->SetStroke($bar_style, $item, $j);
                     $bar_style['fill'] = $this->GetColour($item, $bnum, $j);
                     if (!is_null($item->value)) {
                         $this->Bar($item->value, $bar, $item->value >= 0 ? $ypos : $yneg);
                         if ($item->value < 0) {
                             $yneg += $item->value;
                         } else {
                             $ypos += $item->value;
                         }
                         if ($bar['height'] > 0) {
                             ++$bars_shown[$j];
                             $show_label = $this->AddDataLabel($j, $bnum, $bar, $item, $bar['x'], $bar['y'], $bar['width'], $bar['height']);
                             if ($this->show_tooltips) {
                                 $this->SetTooltip($bar, $item, $j, $item->key, $item->value, !$this->compat_events && $show_label);
                             }
                             if ($this->semantic_classes) {
                                 $bar['class'] = "series{$j}";
                             }
                             $rect = $this->Element('rect', $bar, $bar_style);
                             $bars .= $this->GetLink($item, $k, $rect);
                             unset($bar['id']);
                             // clear for next value
                         }
                     }
                     $this->bar_styles[$j] = $bar_style;
                 }
                 if ($this->show_bar_totals) {
                     if ($ypos) {
                         // make a dataset name for stack total
                         $tds = 'totalpos-' . $start_bar;
                         $this->Bar($ypos, $bar);
                         if (is_callable($this->bar_total_callback)) {
                             $bar_total = call_user_func($this->bar_total_callback, $item->key, $ypos);
                         } else {
                             $bar_total = $ypos;
                         }
                         $this->AddContentLabel($tds, $bnum, $bar['x'], $bar['y'], $bar['width'], $bar['height'], $bar_total);
                     }
                     if ($yneg) {
                         $tds = 'totalneg-' . $start_bar;
                         $this->Bar($yneg, $bar);
                         if (is_callable($this->bar_total_callback)) {
                             $bar_total = call_user_func($this->bar_total_callback, $item->key, $yneg);
                         } else {
                             $bar_total = $yneg;
                         }
                         $this->AddContentLabel($tds, $bnum, $bar['x'], $bar['y'], $bar['width'], $bar['height'], $bar_total);
                     }
                 }
             }
         }
         ++$bnum;
     }
     if (!$this->legend_show_empty) {
         foreach ($bars_shown as $j => $bar) {
             if (!$bar) {
                 $this->bar_styles[$j] = NULL;
             }
         }
     }
     if ($this->semantic_classes) {
         $bars = $this->Element('g', array('class' => 'series'), NULL, $bars);
     }
     $body .= $bars;
     $body .= $this->OverShapes();
     $body .= $this->Axes();
     return $body;
 }
 protected function Draw()
 {
     if ($this->log_axis_y) {
         throw new Exception('log_axis_y not supported by StackedGroupedCylinderGraph');
     }
     $body = $this->Grid() . $this->UnderShapes();
     $group_count = count($this->groups);
     list($group_width, $bspace, $group_unit_width) = GroupedBarGraph::BarPosition($this->bar_width, $this->bar_width_min, $this->x_axes[$this->main_x_axis]->Unit(), $group_count, $this->bar_space, $this->group_space);
     $bar = array('width' => $group_width);
     $bnum = 0;
     $bar_count = count($this->multi_graph);
     $bars_shown = array_fill(0, $bar_count, 0);
     $bars = '';
     $this->ColourSetup($this->multi_graph->ItemsCount(-1), $bar_count);
     $this->block_width = $group_width;
     list($this->bx, $this->by) = $this->Project(-1, 0, $group_width);
     // make the top ellipse, set it as a symbol for re-use
     $top = $this->BarTop();
     // get the translation for the whole bar
     // unit space is 1 deep * $chunk_count wide
     list($tx, $ty) = $this->Project(0, 0, $bspace);
     $all_group = array();
     if ($tx || $ty) {
         $all_group['transform'] = "translate({$tx},{$ty})";
     }
     if ($this->semantic_classes) {
         $all_group['class'] = 'series';
     }
     $group = array();
     foreach ($this->multi_graph as $itemlist) {
         $item = $itemlist[0];
         $k = $item->key;
         $bar_pos = $this->GridPosition($item, $bnum);
         if (!is_null($bar_pos)) {
             for ($l = 0; $l < $group_count; ++$l) {
                 $bar['x'] = $bspace + $bar_pos + $l * $group_unit_width;
                 $start_bar = $this->groups[$l];
                 $end_bar = isset($this->groups[$l + 1]) ? $this->groups[$l + 1] : $bar_count;
                 $ypos = $yneg = 0;
                 // find greatest -/+ bar
                 $max_neg_bar = $max_pos_bar = -1;
                 for ($j = $start_bar; $j < $end_bar; ++$j) {
                     if ($itemlist[$j]->value > 0) {
                         $max_pos_bar = $j;
                     } else {
                         $max_neg_bar = $j;
                     }
                 }
                 for ($j = $start_bar; $j < $end_bar; ++$j) {
                     $item = $itemlist[$j];
                     if (!is_null($item->value)) {
                         $t = $j == $end_bar - 1 ? $top : NULL;
                         $bar_sections = $this->Bar3D($item, $bar, $t, $bnum, $j, $item->value >= 0 ? $ypos : $yneg);
                         if ($item->value < 0) {
                             $yneg += $item->value;
                         } else {
                             $ypos += $item->value;
                         }
                         $group['fill'] = $this->GetColour($item, $bnum, $j);
                         $show_label = $this->AddDataLabel($j, $bnum, $group, $item, $bar['x'] + $tx, $bar['y'] + $ty, $bar['width'], $bar['height']);
                         if ($this->show_tooltips) {
                             $this->SetTooltip($group, $item, $j, $item->key, $item->value);
                         }
                         $link = $this->GetLink($item, $k, $bar_sections);
                         $this->SetStroke($group, $item, $j, 'round');
                         if ($this->semantic_classes) {
                             $group['class'] = "series{$j}";
                         }
                         $bars .= $this->Element('g', $group, NULL, $link);
                         unset($group['id'], $group['class']);
                         // set up legend
                         $cstyle = array('fill' => $this->GetColour($item, $bnum, $j));
                         $this->SetStroke($cstyle, $item, $j);
                         $this->SetLegendEntry($j, $bnum, $item, $cstyle);
                     }
                 }
             }
         }
         ++$bnum;
     }
     if (count($all_group)) {
         $bars = $this->Element('g', $all_group, NULL, $bars);
     }
     $body .= $bars;
     $body .= $this->OverShapes();
     $body .= $this->Axes();
     return $body;
 }
 /**
  * Draws this graph's data labels, and the line graph's data labels
  */
 protected function DrawDataLabels()
 {
     $labels = parent::DrawDataLabels();
     $labels .= $this->linegraph->DrawDataLabels();
     return $labels;
 }
 /**
  * Calculates the bar width, gap to first bar, gap between bars
  * returns an array containing all three
  */
 static function BarPosition($bar_width, $bar_width_min, $unit_width, $group_size, $bar_space, $group_space)
 {
     if (is_numeric($bar_width) && $bar_width >= 1) {
         return GroupedBarGraph::BarPositionFixed($bar_width, $unit_width, $group_size, $group_space);
     } else {
         // bar width dependent on space
         $gap_count = $group_size - 1;
         $gap = $gap_count > 0 ? $group_space : 0;
         $bar_width = $bar_space >= $unit_width ? '1' : $unit_width - $bar_space;
         if ($gap_count > 0 && $gap * $gap_count > $bar_width - $group_size) {
             $gap = ($bar_width - $group_size) / $gap_count;
         }
         $bar_width = ($bar_width - $gap * ($group_size - 1)) / $group_size;
         if ($bar_width < $bar_width_min) {
             return GroupedBarGraph::BarPositionFixed($bar_width_min, $unit_width, $group_size, $group_space);
         }
         $spacing = $bar_width + $gap;
         $offset = $bar_space / 2;
     }
     return array($bar_width, $offset, $spacing);
 }