/lib/artichow/inc/Legend.class.php
PHP | 758 lines | 328 code | 148 blank | 282 comment | 20 complexity | b48f8ead5c371f506ce205a9748d48bf MD5 | raw file
- <?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.
- *
- */
- /**
- * 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(awDrawer $drawer) {
- if($this->hide) {
- return;
- }
- $count = $this->count();
- // No legend to print
- if($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] = $font->getTextWidth($text) + $this->textMargin->left + $this->textMargin->right;
- $heights[$i] = $font->getTextHeight($text);
- $texts[$i] = $text;
- }
- // Maximum height of the font used
- $heightMax = array_max($heights);
- // Get number of columns
- if($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 position
- list($x, $y) = $drawer->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(
- $drawer,
- $p,
- $p->move($width, $height),
- awShadow::OUT
- );
- // Draw legends base
- $this->drawBase($drawer, $p, $width, $height);
- // Draw each legend
- for($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
- $drawer->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 icon
- switch($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 lines
- if($component->getLegendLineColor() !== NULL) {
- $color = $component->getLegendLineColor();
- if($color instanceof awColor and $type !== awLegend::MARKONLY) {
- $drawer->line(
- $color,
- new awLine(
- $p->move(
- $x, // YaPB ??
- $y + $component->getLegendLineThickness() / 2
- ),
- $p->move(
- $x + 10,
- $y + $component->getLegendLineThickness() / 2
- ),
- $component->getLegendLineStyle(),
- $component->getLegendLineThickness()
- )
- );
- $color->free();
- unset($color);
- }
- }
- if($type === awLegend::MARK or $type === awLegend::MARKONLY) {
- $mark = $component->getLegendMark();
- if($mark !== NULL) {
- $mark->draw(
- $drawer,
- $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) {
- $drawer->filledRectangle(
- $component->getLegendBackground(),
- new awLine($from, $to)
- );
- // Draw rectangle border
- $this->border->rectangle(
- $drawer,
- $from->move(0, 0),
- $to->move(0, 0)
- );
- }
- unset($background, $from, $to);
- break;
- }
- }
- // Draw legend text
- /* $drawer->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
- )
- );*/
- $text1 = new awText(
- 'Weekly',
- new Tuffy(8),
- new Color(0, 0, 0, 0),
- 0);
- $text2 = new awText(
- 'Monthly',
- new Tuffy(8),
- new Color(0, 0, 0, 0),
- 0);
-
- $text3 = new awText(
- 'Yearly',
- new Tuffy(8),
- new Color(0, 0, 0, 0),
- 0);
- $point1 = new awPoint(
- 412,
- 7
- );
-
- $point2 = new awPoint(
- 412,
- 30
- );
-
- $point3 = new awPoint(
- 412,
- 54
- );
-
- $drawer->string($text1, $point1);
- $drawer->string($text2, $point2);
- $drawer->string($text3, $point3);
- }
- private function drawBase(awDrawer $drawer, awPoint $p, $width, $height) {
- $this->border->rectangle(
- $drawer,
- $p,
- $p->move($width, $height)
- );
- $size = $this->border->visible() ? 1 : 0;
- $drawer->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');
- ?>