Rev 61 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/** This work is hereby released into the Public Domain.* To view a copy of the public domain dedication,* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.**/require_once dirname(__FILE__)."/../Graph.class.php";/*** Some legends** @package Artichow*/class awLegend implements awPositionable {/*** Legends added** @var array*/protected $legends = array();/*** The current component** @var Component*/protected $component;/*** Background color or gradient** @var Color, Gradient*/protected $background;/*** Text color** @var Color*/protected $textColor;/*** Text font** @var Font*/protected $textFont;/*** Text margin** @var Side*/protected $textMargin;/*** Number of columns** @var int*/protected $columns = NULL;/*** Number of rows** @var int*/protected $rows = NULL;/*** Legend position** @var Point*/protected $position;/*** Hide legend ?** @var bool*/protected $hide = FALSE;/*** Space between each legend** @var int*/protected $space = 4;/*** Horizontal alignment** @var int*/protected $hAlign;/*** Vertical alignment** @var int*/protected $vAlign;/*** Margin** @var array Array for left, right, top and bottom margins*/private $margin;/*** Legend shadow** @var Shadow*/public $shadow;/*** Legend border** @var Border*/public $border;/*** Line legend** @var int*/const LINE = 1;/*** Color/Gradient background legend** @var int*/const BACKGROUND = 2;/*** Use marks and line as legend** @var int*/const MARK = 3;/*** Use marks as legend** @var int*/const MARKONLY = 4;/*** Right side model** @var int*/const MODEL_RIGHT = 1;/*** Bottom side model** @var int*/const MODEL_BOTTOM = 2;/*** Build the legend** @param int $model Legend model*/public function __construct($model = awLegend::MODEL_RIGHT) {$this->shadow = new awShadow(awShadow::LEFT_BOTTOM);$this->border = new awBorder;$this->textMargin = new awSide(4);$this->setModel($model);}/*** Set a predefined model for the legend** @param int $model*/public function setModel($model) {$this->setBackgroundColor(new awColor(255, 255, 255, 15));$this->setPadding(8, 8, 8, 8);$this->setTextFont(new awFont2);$this->shadow->setSize(3);switch($model) {case awLegend::MODEL_RIGHT :$this->setColumns(1);$this->setAlign(awLegend::RIGHT, awLegend::MIDDLE);$this->setPosition(0.96, 0.50);break;case awLegend::MODEL_BOTTOM :$this->setRows(1);$this->setAlign(awLegend::CENTER, awLegend::TOP);$this->setPosition(0.50, 0.92);break;default :$this->setPosition(0.5, 0.5);break;}}/*** Hide legend ?** @param bool $hide TRUE to hide legend, FALSE otherwise*/public function hide($hide = TRUE) {$this->hide = (bool)$hide;}/*** Show legend ?** @param bool $show*/public function show($show = TRUE) {$this->hide = (bool)!$show;}/*** Add a Legendable object to the legend** @param awLegendable $legendable* @param string $title Legend title* @param int $type Legend type (default to awLegend::LINE)*/public function add(awLegendable $legendable, $title, $type = awLegend::LINE) {$legend = array($legendable, $title, $type);$this->legends[] = $legend;}/*** Change legend padding** @param int $left* @param int $right* @param int $top* @param int $bottom*/public function setPadding($left, $right, $top, $bottom) {$this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom);}/*** Change space between each legend** @param int $space*/public function setSpace($space) {$this->space = (int)$space;}/*** Change alignment** @param int $h Horizontal alignment* @param int $v Vertical alignment*/public function setAlign($h = NULL, $v = NULL) {if($h !== NULL) {$this->hAlign = (int)$h;}if($v !== NULL) {$this->vAlign = (int)$v;}}/*** Change number of columns** @param int $columns*/public function setColumns($columns) {$this->rows = NULL;$this->columns = (int)$columns;}/*** Change number of rows** @param int $rows*/public function setRows($rows) {$this->columns = NULL;$this->rows = (int)$rows;}/*** Change legend position* X and Y positions must be between 0 and 1.** @param float $x* @param float $y*/public function setPosition($x = NULL, $y = NULL) {$x = (is_null($x) and !is_null($this->position)) ? $this->position->x : $x;$y = (is_null($y) and !is_null($this->position)) ? $this->position->y : $y;$this->position = new awPoint($x, $y);}/*** Get legend position** @return Point*/public function getPosition() {return $this->position;}/*** Change text font** @param awFont $font*/public function setTextFont(awFont $font) {$this->textFont = $font;}/*** Change text margin** @param int $left* @param int $right*/public function setTextMargin($left, $right) {$this->textMargin->set($left, $right);}/*** Change text color** @param awColor $color*/public function setTextColor(awColor $color) {$this->textColor = $color;}/*** Change background** @param mixed $background*/public function setBackground($background) {$this->background = $background;}/*** Change background color** @param awColor $color*/public function setBackgroundColor(awColor $color) {$this->background = $color;}/*** Change background gradient** @param awGradient $gradient*/public function setBackgroundGradient(awGradient $gradient) {$this->background = $gradient;}/*** Count the number of Legendable objects in the legend** @return int*/public function count() {return count($this->legends);}public function draw(awDriver $driver) {if($this->hide) {return;}$count = $this->count();// No legend to printif($count === 0) {return;}// Get text widths and heights of each element of the legend$widths = array();$heights = array();$texts = array();for($i = 0; $i < $count; $i++) {list(, $title, ) = $this->legends[$i];$text = new awText($title,$this->textFont,$this->textColor,0);// $font = $text->getFont();$widths[$i] = $driver->getTextWidth($text) + $this->textMargin->left + $this->textMargin->right;$heights[$i] = $driver->getTextHeight($text);$texts[$i] = $text;}// Maximum height of the font used$heightMax = array_max($heights);// Get number of columnsif($this->columns !== NULL) {$columns = $this->columns;} else if($this->rows !== NULL) {$columns = ceil($count / $this->rows);} else {$columns = $count;}// Number of rows$rows = (int)ceil($count / $columns);// Get maximum with of each column$widthMax = array();for($i = 0; $i < $count; $i++) {// Get column width$column = $i % $columns;if(array_key_exists($column, $widthMax) === FALSE) {$widthMax[$column] = $widths[$i];} else {$widthMax[$column] = max($widthMax[$column], $widths[$i]);}}$width = $this->padding[0] + $this->padding[1] - $this->space;for($i = 0; $i < $columns; $i++) {$width += $this->space + 5 + 10 + $widthMax[$i];}$height = ($heightMax + $this->space) * $rows - $this->space + $this->padding[2] + $this->padding[3];// Look for legends positionlist($x, $y) = $driver->getSize();$p = new awPoint($this->position->x * $x,$this->position->y * $y);switch($this->hAlign) {case awLegend::CENTER :$p->x -= $width / 2;break;case awLegend::RIGHT :$p->x -= $width;break;}switch($this->vAlign) {case awLegend::MIDDLE :$p->y -= $height / 2;break;case awLegend::BOTTOM :$p->y -= $height;break;}// Draw legend shadow$this->shadow->draw($driver,$p,$p->move($width, $height),awShadow::OUT);// Draw legends base$this->drawBase($driver, $p, $width, $height);// Draw each legendfor($i = 0; $i < $count; $i++) {list($component, $title, $type) = $this->legends[$i];$column = $i % $columns;$row = (int)floor($i / $columns);// Get width of all previous columns$previousColumns = 0;for($j = 0; $j < $column; $j++) {$previousColumns += $this->space + 10 + 5 + $widthMax[$j];}// Draw legend text$driver->string($texts[$i],$p->move($this->padding[0] + $previousColumns + 10 + 5 + $this->textMargin->left,$this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $heights[$i] / 2));// Draw legend iconswitch($type) {case awLegend::LINE :case awLegend::MARK :case awLegend::MARKONLY :// Get vertical position$x = $this->padding[0] + $previousColumns;$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $component->getLegendLineThickness();// Draw two linesif($component->getLegendLineColor() !== NULL) {$color = $component->getLegendLineColor();if($color instanceof awColor and $type !== awLegend::MARKONLY) {$driver->line($color,new awLine($p->move($x, // YaPB ??$y + $component->getLegendLineThickness() / 2),$p->move($x + 10,$y + $component->getLegendLineThickness() / 2),$component->getLegendLineStyle(),$component->getLegendLineThickness()));unset($color);}}if($type === awLegend::MARK or $type === awLegend::MARKONLY) {$mark = $component->getLegendMark();if($mark !== NULL) {$mark->draw($driver,$p->move($x + 5.5,$y + $component->getLegendLineThickness() / 2));}unset($mark);}break;case awLegend::BACKGROUND :// Get vertical position$x = $this->padding[0] + $previousColumns;$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - 5;$from = $p->move($x,$y);$to = $p->move($x + 10,$y + 10);$background = $component->getLegendBackground();if($background !== NULL) {$driver->filledRectangle($component->getLegendBackground(),new awLine($from, $to));// Draw rectangle border$this->border->rectangle($driver,$from->move(0, 0),$to->move(0, 0));}unset($background, $from, $to);break;}}}private function drawBase(awDriver $driver, awPoint $p, $width, $height) {$this->border->rectangle($driver,$p,$p->move($width, $height));$size = $this->border->visible() ? 1 : 0;$driver->filledRectangle($this->background,new awLine($p->move($size, $size),$p->move($width - $size, $height - $size)));}}registerClass('Legend');/*** You can add a legend to components which implements this interface** @package Artichow*/interface awLegendable {/*** Get the line type** @return int*/public function getLegendLineStyle();/*** Get the line thickness** @return int*/public function getLegendLineThickness();/*** Get the color of line** @return Color*/public function getLegendLineColor();/*** Get the background color or gradient of an element of the component** @return Color, Gradient*/public function getLegendBackground();/*** Get a Mark object** @return Mark*/public function getLegendMark();}registerInterface('Legendable');?>