diff --git a/docs/changes/1.0.0.md b/docs/changes/1.0.0.md index 230992c33..14b9572c3 100644 --- a/docs/changes/1.0.0.md +++ b/docs/changes/1.0.0.md @@ -43,6 +43,9 @@ - Support for managing missing values in Chart - @TonisOrmisson GH-581 & @Progi1986 GH-659 - ODPresentation Writer - PowerPoint2007 Writer +- Support for defining ticks label position for Axis in Chart - @Web-Mobiledev GH-591 & @Progi1986 GH-660 + - ODPresentation Writer + - PowerPoint2007 Writer ## Project Management - Migrated from Travis CI to Github Actions - @Progi1984 GH-635 diff --git a/docs/usage/shapes/chart.md b/docs/usage/shapes/chart.md index 0e6c8b315..0e9590da6 100644 --- a/docs/usage/shapes/chart.md +++ b/docs/usage/shapes/chart.md @@ -109,6 +109,28 @@ $shape->getPlotArea()->setType($line); $shape->getPlotArea()->getAxisX()->getOutline()->setWidth(10); $shape->getPlotArea()->getAxisX()->getOutline()->getFill()->setFillType(Fill::FILL_SOLID)->setStartColor(new Color(Color::COLOR_BLUE)); ``` +#### Tick Label Position + +You can define the tick label position with the `setTickLabelPosition` method. +For resetting it, you pass `Axis::TICK_LABEL_POSITION_NEXT_TO` as parameter to this method. + +Differents types are available: + +* `Axis::TICK_LABEL_POSITION_HIGH`: **Labels are at the high end of the perpendicular axis** +* `Axis::TICK_LABEL_POSITION_LOW`: **Labels are at the low end of the perpendicular axis** +* `Axis::TICK_LABEL_POSITION_NEXT_TO`: **Labels are next to the axis** (default) + +``` php +createChartShape(); +$shape->getPlotArea()->setType($line); +$shape->getPlotArea()->getAxisY()->setTickLabelPosition(Axis::TICK_LABEL_POSITION_LOW); +``` #### Tick Marks For Axis Y, you can define tick mark with `setMinorTickMark` & `setMajorTickMark` methods. diff --git a/src/PhpPresentation/Shape/Chart/Axis.php b/src/PhpPresentation/Shape/Chart/Axis.php index 9dde35354..bc0d88d6b 100644 --- a/src/PhpPresentation/Shape/Chart/Axis.php +++ b/src/PhpPresentation/Shape/Chart/Axis.php @@ -32,6 +32,10 @@ class Axis implements ComparableInterface public const TICK_MARK_INSIDE = 'in'; public const TICK_MARK_OUTSIDE = 'out'; + public const TICK_LABEL_POSITION_NEXT_TO = 'nextTo'; + public const TICK_LABEL_POSITION_HIGH = 'high'; + public const TICK_LABEL_POSITION_LOW = 'low'; + /** * Title. * @@ -88,6 +92,11 @@ class Axis implements ComparableInterface */ protected $majorTickMark = self::TICK_MARK_NONE; + /** + * @var string + */ + protected $tickLabelPosition = self::TICK_LABEL_POSITION_NEXT_TO; + /** * @var float */ @@ -452,4 +461,30 @@ public function setIsVisible(bool $value): self return $this; } + + /** + * @return string + */ + public function getTickLabelPosition(): string + { + return $this->tickLabelPosition; + } + + /** + * @param string $value + * + * @return self + */ + public function setTickLabelPosition(string $value = self::TICK_LABEL_POSITION_NEXT_TO): self + { + if (in_array($value, [ + self::TICK_LABEL_POSITION_HIGH, + self::TICK_LABEL_POSITION_LOW, + self::TICK_LABEL_POSITION_NEXT_TO, + ])) { + $this->tickLabelPosition = $value; + } + + return $this; + } } diff --git a/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php b/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php index fc53d0e23..1a48fd2e9 100644 --- a/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php +++ b/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php @@ -7,6 +7,7 @@ use PhpOffice\Common\Text; use PhpOffice\Common\XMLWriter; use PhpOffice\PhpPresentation\Shape\Chart; +use PhpOffice\PhpPresentation\Shape\Chart\Axis; use PhpOffice\PhpPresentation\Shape\Chart\Title; use PhpOffice\PhpPresentation\Shape\Chart\Type\AbstractTypeBar; use PhpOffice\PhpPresentation\Shape\Chart\Type\AbstractTypePie; @@ -309,6 +310,20 @@ private function writeAxisMainStyle(Chart\Axis $axis, string $styleName, bool $i $this->xmlContent->writeAttributeIf($isPieChart, 'chart:reverse-direction', 'true'); $this->xmlContent->writeAttributeIf(null !== $axis->getMinBounds(), 'chart:minimum', $axis->getMinBounds()); $this->xmlContent->writeAttributeIf(null !== $axis->getMaxBounds(), 'chart:maximum', $axis->getMaxBounds()); + switch ($axis->getTickLabelPosition()) { + case Axis::TICK_LABEL_POSITION_NEXT_TO: + $this->xmlContent->writeAttribute('chart:axis-label-position', 'near-axis'); + break; + case Axis::TICK_LABEL_POSITION_HIGH: + $this->xmlContent->writeAttribute('chart:axis-position', '0'); + $this->xmlContent->writeAttribute('chart:axis-label-position', 'outside-end'); + break; + case Axis::TICK_LABEL_POSITION_LOW: + $this->xmlContent->writeAttribute('chart:axis-position', '0'); + $this->xmlContent->writeAttribute('chart:axis-label-position', 'outside-start'); + $this->xmlContent->writeAttribute('chart:tick-mark-position', 'at-axis'); + break; + } $this->xmlContent->endElement(); // style:graphic-properties $this->xmlContent->startElement('style:graphic-properties'); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php b/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php index a031d0bc6..eab8f4b1f 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php @@ -2284,7 +2284,7 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty // c:tickLblPos $objWriter->startElement('c:tickLblPos'); - $objWriter->writeAttribute('val', 'nextTo'); + $objWriter->writeAttribute('val', $oAxis->getTickLabelPosition()); $objWriter->endElement(); // c:spPr diff --git a/tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php b/tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php index 40f273df9..7ae33da24 100644 --- a/tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php +++ b/tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php @@ -135,6 +135,21 @@ public function testOutline(): void $this->assertInstanceOf(Outline::class, $object->getOutline()); } + public function testTickLabelPosition(): void + { + $object = new Axis(); + + $this->assertEquals(Axis::TICK_LABEL_POSITION_NEXT_TO, $object->getTickLabelPosition()); + $this->assertInstanceOf(Axis::class, $object->setTickLabelPosition(Axis::TICK_LABEL_POSITION_HIGH)); + $this->assertEquals(Axis::TICK_LABEL_POSITION_HIGH, $object->getTickLabelPosition()); + $this->assertInstanceOf(Axis::class, $object->setTickLabelPosition(Axis::TICK_LABEL_POSITION_NEXT_TO)); + $this->assertEquals(Axis::TICK_LABEL_POSITION_NEXT_TO, $object->getTickLabelPosition()); + $this->assertInstanceOf(Axis::class, $object->setTickLabelPosition(Axis::TICK_LABEL_POSITION_LOW)); + $this->assertEquals(Axis::TICK_LABEL_POSITION_LOW, $object->getTickLabelPosition()); + $this->assertInstanceOf(Axis::class, $object->setTickLabelPosition('Unauthorized')); + $this->assertEquals(Axis::TICK_LABEL_POSITION_LOW, $object->getTickLabelPosition()); + } + public function testTickMark(): void { $value = Axis::TICK_MARK_INSIDE; diff --git a/tests/PhpPresentation/Tests/Writer/ODPresentation/ObjectsChartTest.php b/tests/PhpPresentation/Tests/Writer/ODPresentation/ObjectsChartTest.php index 89b149341..20eb4bb2d 100644 --- a/tests/PhpPresentation/Tests/Writer/ODPresentation/ObjectsChartTest.php +++ b/tests/PhpPresentation/Tests/Writer/ODPresentation/ObjectsChartTest.php @@ -4,6 +4,7 @@ use PhpOffice\Common\Drawing as CommonDrawing; use PhpOffice\PhpPresentation\Shape\Chart; +use PhpOffice\PhpPresentation\Shape\Chart\Axis; use PhpOffice\PhpPresentation\Shape\Chart\Gridlines; use PhpOffice\PhpPresentation\Shape\Chart\Legend; use PhpOffice\PhpPresentation\Shape\Chart\Marker; @@ -511,6 +512,50 @@ public function testTypeAxisBounds(): void $this->assertIsSchemaOpenDocumentNotValid('1.2'); } + public function testTypeAxisTickLabelPosition(): void + { + $element = '/office:document-content/office:automatic-styles/style:style[@style:name=\'styleAxisX\']/style:chart-properties'; + + $oSeries = new Series('Series', $this->seriesData); + $oLine = new Line(); + $oLine->addSeries($oSeries); + $oShape = $this->oPresentation->getActiveSlide()->createChartShape(); + $oShape->getPlotArea()->setType($oLine); + + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:axis-label-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:axis-label-position', 'near-axis'); + $this->assertZipXmlAttributeNotExists('Object 1/content.xml', $element, 'chart:axis-position'); + $this->assertZipXmlAttributeNotExists('Object 1/content.xml', $element, 'chart:tick-mark-position'); + + // chart:title : Element chart failed to validate attributes + $this->assertIsSchemaOpenDocumentNotValid('1.2'); + + $this->resetPresentationFile(); + $oShape->getPlotArea()->getAxisX()->setTickLabelPosition(Axis::TICK_LABEL_POSITION_HIGH); + + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:axis-label-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:axis-label-position', 'outside-end'); + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:axis-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:axis-position', '0'); + $this->assertZipXmlAttributeNotExists('Object 1/content.xml', $element, 'chart:tick-mark-position'); + + // chart:title : Element chart failed to validate attributes + $this->assertIsSchemaOpenDocumentNotValid('1.2'); + + $this->resetPresentationFile(); + $oShape->getPlotArea()->getAxisX()->setTickLabelPosition(Axis::TICK_LABEL_POSITION_LOW); + + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:axis-label-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:axis-label-position', 'outside-start'); + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:axis-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:axis-position', '0'); + $this->assertZipXmlAttributeExists('Object 1/content.xml', $element, 'chart:tick-mark-position'); + $this->assertZipXmlAttributeEquals('Object 1/content.xml', $element, 'chart:tick-mark-position', 'at-axis'); + + // chart:title : Element chart failed to validate attributes + $this->assertIsSchemaOpenDocumentNotValid('1.2'); + } + public function testTypeBar(): void { $oSeries = new Series('Series', ['Jan' => '1', 'Feb' => '5', 'Mar' => '2']); diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php index 41de5a90d..0803585b3 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php @@ -414,6 +414,37 @@ public function testTypeAxisBounds(): void $this->assertIsSchemaECMA376Valid(); } + public function testTypeAxisTickLabelPosition(): void + { + $element = '/c:chartSpace/c:chart/c:plotArea/c:valAx/c:tickLblPos'; + + $oSeries = new Series('Downloads', $this->seriesData); + $oLine = new Line(); + $oLine->addSeries($oSeries); + $oShape = $this->oPresentation->getActiveSlide()->createChartShape(); + $oShape->getPlotArea()->setType($oLine); + + $this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element); + $this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', Axis::TICK_LABEL_POSITION_NEXT_TO); + + $this->assertIsSchemaECMA376Valid(); + + $oShape->getPlotArea()->getAxisY()->setTickLabelPosition(Axis::TICK_LABEL_POSITION_HIGH); + $this->resetPresentationFile(); + + $this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element); + $this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', Axis::TICK_LABEL_POSITION_HIGH); + $this->assertIsSchemaECMA376Valid(); + + $oShape->getPlotArea()->getAxisY()->setTickLabelPosition(Axis::TICK_LABEL_POSITION_LOW); + $this->resetPresentationFile(); + + $this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $element); + $this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $element, 'val', Axis::TICK_LABEL_POSITION_LOW); + + $this->assertIsSchemaECMA376Valid(); + } + public function testTypeAxisTickMark(): void { $value = Axis::TICK_MARK_CROSS;