summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Chart/Primitive/Path.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Chart/Primitive/Path.php')
-rw-r--r--library/Icinga/Chart/Primitive/Path.php187
1 files changed, 187 insertions, 0 deletions
diff --git a/library/Icinga/Chart/Primitive/Path.php b/library/Icinga/Chart/Primitive/Path.php
new file mode 100644
index 0000000..b9d5f7b
--- /dev/null
+++ b/library/Icinga/Chart/Primitive/Path.php
@@ -0,0 +1,187 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Chart\Primitive;
+
+use DOMDocument;
+use DOMElement;
+use Icinga\Chart\Render\RenderContext;
+use Icinga\Chart\Format;
+
+/**
+ * Drawable for creating a svg path element
+ */
+class Path extends Styleable implements Drawable
+{
+ /**
+ * Syntax template for moving
+ *
+ * @see http://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands
+ */
+ const TPL_MOVE = 'M %s %s ';
+
+ /**
+ * Syntax template for bezier curve
+ *
+ * @see http://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
+ */
+ const TPL_BEZIER = 'S %s %s ';
+
+ /**
+ * Syntax template for straight lines
+ *
+ * @see http://www.w3.org/TR/SVG/paths.html#PathDataLinetoCommands
+ */
+ const TPL_STRAIGHT = 'L %s %s ';
+
+ /**
+ * The default stroke width
+ *
+ * @var int
+ */
+ public $strokeWidth = 1;
+
+ /**
+ * True to treat coordinates as absolute values
+ *
+ * @var bool
+ */
+ protected $isAbsolute = false;
+
+ /**
+ * The points to draw, in the order they are drawn
+ *
+ * @var array
+ */
+ protected $points = array();
+
+ /**
+ * True to draw the path discrete, i.e. make hard steps between points
+ *
+ * @var bool
+ */
+ protected $discrete = false;
+
+ /**
+ * Create the path using the given points
+ *
+ * @param array $points Either a single [x, y] point or an array of x, y points
+ */
+ public function __construct(array $points)
+ {
+ $this->append($points);
+ }
+
+ /**
+ * Append a single point or an array of points to this path
+ *
+ * @param array $points Either a single [x, y] point or an array of x, y points
+ *
+ * @return $this Fluid interface
+ */
+ public function append(array $points)
+ {
+ if (count($points) === 0) {
+ return $this;
+ }
+ if (!is_array($points[0])) {
+ $points = array($points);
+ }
+ $this->points = array_merge($this->points, $points);
+ return $this;
+ }
+
+ /**
+ * Prepend a single point or an array of points to this path
+ *
+ * @param array $points Either a single [x, y] point or an array of x, y points
+ *
+ * @return $this Fluid interface
+ */
+ public function prepend(array $points)
+ {
+ if (count($points) === 0) {
+ return $this;
+ }
+ if (!is_array($points[0])) {
+ $points = array($points);
+ }
+ $this->points = array_merge($points, $this->points);
+ return $this;
+ }
+
+ /**
+ * Set this path to be discrete
+ *
+ * @param boolean $bool True to draw discrete or false to draw straight lines between points
+ *
+ * @return $this Fluid interface
+ */
+ public function setDiscrete($bool)
+ {
+ $this->discrete = $bool;
+ return $this;
+ }
+
+ /**
+ * Mark this path as containing absolute coordinates
+ *
+ * @return $this Fluid interface
+ */
+ public function toAbsolute()
+ {
+ $this->isAbsolute = true;
+ return $this;
+ }
+
+ /**
+ * Create the SVG representation from this Drawable
+ *
+ * @param RenderContext $ctx The context to use for rendering
+ * @return DOMElement The SVG Element
+ */
+ public function toSvg(RenderContext $ctx)
+ {
+ $doc = $ctx->getDocument();
+ $group = $doc->createElement('g');
+
+ $pathDescription = '';
+ $tpl = self::TPL_MOVE;
+ $lastPoint = null;
+ foreach ($this->points as $point) {
+ if (!$this->isAbsolute) {
+ $point = $ctx->toAbsolute($point[0], $point[1]);
+ }
+ $point[0] = Format::formatSVGNumber($point[0]);
+ $point[1] = Format::formatSVGNumber($point[1]);
+ if ($lastPoint && $this->discrete) {
+ $pathDescription .= sprintf($tpl, $point[0], $lastPoint[1]);
+ }
+ $pathDescription .= vsprintf($tpl, $point);
+ $lastPoint = $point;
+ $tpl = self::TPL_STRAIGHT;
+ }
+
+ $path = $doc->createElement('path');
+
+ $id = $this->id ?? uniqid('path-');
+ $path->setAttribute('id', $id);
+ $this->setId($id);
+
+ $path->setAttribute('d', $pathDescription);
+
+ $this->applyAttributes($path);
+ $style = new DOMDocument();
+ $style->loadHTML($this->getStyle());
+
+ $path->appendChild(
+ $path->ownerDocument->importNode(
+ $style->getElementsByTagName('style')->item(0),
+ true
+ )
+ );
+
+ $group->appendChild($path);
+ return $group;
+ }
+}